간단한 babel 매크로 작성 방법
12064 단어 babelmacrojavascript
babel-plugin-macros
는 JavaScript(또는 Flow)용 매크로를 작성하기 위한 babel용 플러그인입니다. 여기서 중요한 부분은 babel-plugin-macros
가 포함되자마자 매크로를 사용하기 위해 babel 구성을 건드릴 필요가 없다는 것입니다(다른 babel 플러그인과 달리). 이것은 Create React App과 같은 잠긴 설정에서 매우 유용합니다. 또한 명시적이라는 점이 마음에 듭니다. 매크로가 사용되는 위치를 명확하게 볼 수 있습니다.일
매크로로 쉽게 풀 수 있는 장난감 크기 문제를 가져왔습니다.
Webpack에서 동적
import
을 사용하면 1.chunk.js
, 2.chunk.js
와 같이 청크에 대해 읽기 어려운 이름을 생성합니다(적어도 CRA에서 수행하는 작업입니다). 이 문제를 해결하기 위해 매직 주석 /* webpackChunkName: MyComponent */
을 사용할 수 있으므로 MyComponent.chunk.js
를 얻을 수 있지만 매번 이 주석을 손으로 두는 것은 성가신 일입니다. 이것을 수정하기 위해 정확히 babel 매크로를 작성해봅시다.우리는 다음과 같은 코드를 원합니다:
import wcImport from "webpack-comment-import.macro";
const asyncModule = wcImport("./MyComponent");
로 변환하려면
const asyncModule = import(/* webpackChunkName: MyComponent */ "./MyComponent");
상용구
그래서 바로 코딩으로 넘어가고 싶기 때문에 상용구에 시간을 들이지 않겠습니다. 초기 코드를 볼 수 있는 tag
boilerplate
GitHub 리포지토리가 있습니다.export default createMacro(webpackCommentImportMacros);
function webpackCommentImportMacros({ references, state, babel }) {
// lets walk through all calls of the macro
references.default.map(referencePath => {
// check if it is call expression e.g. someFunction("blah-blah")
if (referencePath.parentPath.type === "CallExpression") {
// call our macro
requireWebpackCommentImport({ referencePath, state, babel });
} else {
// fail otherwise
throw new Error(
`This is not supported: \`${referencePath
.findParent(babel.types.isExpression)
.getSource()}\`. Please see the webpack-comment-import.macro documentation`,
);
}
});
}
function requireWebpackCommentImport({ referencePath, state, babel }) {
// Our macro which we need to implement
}
테스트 및 빌드 스크립트도 구성되어 있습니다. 처음부터 쓴게 아닙니다. raw.macro 에서 복사했습니다.
코딩하자
우선
babel.types
을 얻습니다. 여기에 거래가 있습니다. 매크로로 작업할 때 주로 하는 것은 AST(소스 코드 표현)를 조작하는 것이며 babel.types
에는 babel AST에서 사용되는 가능한 모든 유형의 표현식에 대한 참조가 포함되어 있습니다. babel.types
readme babel AST로 작업하려는 경우 가장 유용한 참조입니다.function requireWebpackCommentImport({ referencePath, state, babel }) {
const t = babel.types;
referencePath
는 wcImport
에서 const asyncModule = wcImport("./MyComponent");
이므로 레벨을 더 높여야 합니다. wcImport("./MyComponent")
. const callExpressionPath = referencePath.parentPath;
let webpackCommentImportPath;
이제 우리는 우리 함수가 호출된 인수를 얻을 수 있습니다. 재미있는 일이 일어나지 않도록 하기 위해
try/catch
를 사용합시다. 함수 호출의 첫 번째 인수는 가져오기 경로로 가정합니다. "./MyComponent"
. try {
webpackCommentImportPath = callExpressionPath.get("arguments")[0].evaluate()
.value;
} catch (err) {
// swallow error, print better error below
}
if (webpackCommentImportPath === undefined) {
throw new Error(
`There was a problem evaluating the value of the argument for the code: ${callExpressionPath.getSource()}. ` +
`If the value is dynamic, please make sure that its value is statically deterministic.`,
);
}
마지막으로 AST 조작 -
wcImport("./MyComponent")
를 import("./MyComponent");
로 바꾸자. referencePath.parentPath.replaceWith(
t.callExpression(t.identifier("import"), [
t.stringLiteral(webpackCommentImportPath),
]),
);
경로의 마지막 부분을 구합시다.
a/b/c
를 c
로 변환합니다. const webpackCommentImportPathParts = webpackCommentImportPath.split("/");
const identifier =
webpackCommentImportPathParts[webpackCommentImportPathParts.length - 1];
그리고 가져오기의 첫 번째 인수 앞에 매직 구성 요소를 넣습니다.
referencePath.parentPath
.get("arguments")[0]
.addComment("leading", ` webpackChunkName: ${identifier} `);
}
그리고 이것이다. 나는 그것을 짧게 유지하려고 노력했다. 나는 많은 세부 사항에 뛰어 들지 않았고 질문을하십시오.
추신
Babel 문서는 약간 어렵습니다. 가장 쉬운 방법은 다음과 같습니다.
console.log(referencePath.parentPath.type)
로 표현식의 유형을 검사하고 babel.types
에서 이에 대해 읽으십시오.전체 소스 코드는 here
도움이 되기를 바랍니다. 시도 해봐. 어떻게 되는지 알려주세요. 또는 단순히 babel 매크로에 대한 아이디어를 공유하십시오.
및 github에서 나를 따르십시오.
Reference
이 문제에 관하여(간단한 babel 매크로 작성 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/stereobooster/how-to-write-simple-babel-macro-1al1텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)