롤업으로 최신 JavaScript 제공
20375 단어 rollupwebdevjavascriptes2017
This post is a few months old, but it still gets a few hits on my blog everyday so maybe it can help people.
코드베이스에서 ES2017(및 최신) 구문을 사용하는 것과 이를 사용자에게 보내는 것은 별개입니다.
IE11을 지원하거나
@babel/preset-env
을 사용해야 하거나 단일 번들(코드 분할 포함)을 배송해야 하는 경우 브라우저가 classes 또는 async/await을 완벽하게 이해할 수 있더라도 모든 사람에게 ES5를 보낼 가능성이 있습니다. .이는 우리가 필요 이상으로 더 많은 코드를 보내고 장기적으로 일부 "무료"성능 향상을 놓칠 것이기 때문에 차선책입니다.
Six Speed project에서 ES5 트랜스파일 버전과 비교한 ES6 기능의 성능에 대해 자세히 알아볼 수 있습니다. 브라우저 공급업체가 새 구문의 성능을 정기적으로 개선하기 때문에 현상 유지는 고정되어 있지 않습니다(this 및 this 참조).
또한 모든
preset-env
타겟이 최신 상태이더라도 Babel may still be transpiling some syntax because of edge-cases 입니다. 게다가, 우리의 의존성은 아마도 어쨌든 ES5로 변환될 것입니다.더 나은 방법은 트랜스파일된 ES5를 레거시 브라우저로, ES2017을 최신 브라우저로 최대한 많이 제공하는 것입니다.
이를 달성하기 위해 취해야 할 단계는 다음과 같습니다.
preset-modules
대신 작업 예제 in this repo 을 볼 수 있습니다.
번들링
롤업을 사용하는 경우 이미 ES 모듈 또는 기본적으로 폴백을 출력할 수 있습니다.
그러나 다른 구성으로 각 빌드를 생성하려면 약간의 구성을 추가해야 합니다.
이를 수행하는 한 가지 방법은 npm 스크립트에서 환경 변수
preset-env
을 사용하는 것입니다.롤업 및 Terser 구성
// package.json
{
/** ... **/
"scripts": {
"build": "npm-run-all --parallel \"build:*\"",
"build:legacy": "env ROLLUP_BUILD_TYPE=\"legacy\" rollup -c",
"build:modern": "env ROLLUP_BUILD_TYPE=\"modern\" rollup -c"
},
"devDependencies" : {
"npm-run-all": "...",
"rollup": "..."
}
/** ... **/
}
// rollup.config.js
export default () => {
const buildType = typeof process.env.ROLLUP_BUILD_TYPE !== "undefined" ? process.env.ROLLUP_BUILD_TYPE : "modern";
return {
input: ["./src/index.jsx"],
output: buildType === "modern" ?
{
dir: `/public/js/system/`,
format: "system"
} :
{
dir: `/public/js/esm/`,
format: "esm"
},
plugins: [
/** ... **/
babel({
/**
* Uncomment to ignore node_modules. This will accelerate yur build,
* but prevent you from using modern syntax in your dependencies
*/
// exclude: "node_modules/**"
}),
terser({
compress: {
unused: false,
collapse_vars: false
},
sourcemap: true,
ecma: buildType === "legacy" ? 5 : 2017,
safari10: true,
})
/** ... **/
]
};
};
Babel에서 node_modules/를 제외하지 않은 방법에 주목하세요. 이렇게 하면 최신 구문을 내보내는 경우 종속성을 최적으로 변환할 수 있습니다. 나중에 자세히 설명합니다.
Terser은 우리가 사용하는 언어의 버전을 알려야 하는 축소기입니다.
바벨 구성
Babel 7은 정적 개체 대신 함수로 구성할 수 있습니다. 조건부 및 주석이 달린 코드를 작성하기 위해 이 기능을 활용할 수 있습니다.
우리의 목표는 가능한 한 적게 트랜스파일하는 것임을 기억하십시오. 이 예에서는 반응용 사전 설정과 ES2020 features용 플러그인을 포함합니다. 플러그인은 최신 브라우저에서도 한동안 계속 사용됩니다.
// in babel.config.cjs
module.exports = function(api) {
api.cache.invalidate(() => [
process.env.NODE_ENV,
process.env.ROLLUP_BUILD_TYPE
].join("-"));
const environment = api.env();
const modern = process.env.ROLLUP_BUILD_TYPE === "modern";
/**
* Will be used for the legacy build
*/
const presetEnv = [
"@babel/preset-env",
{
modules: false,
targets: {
browsers: [">0.25%", "not op_mini all"],
},
},
];
/**
* Will be used for the modern build
*/
const presetModule = [
"@babel/preset-modules",
{
loose: true,
},
];
const alwaysUsedPresets = ["@babel/preset-react"];
const alwaysUsedPlugins = [
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
];
/**
* Only loaded in the legacy build
*/
const legacyPlugins = [
"@babel/plugin-proposal-object-rest-spread"
];
const productionConfig =
modern === "modern"
? {
/**
* Modern build
*/
presets: [
presetModule,
...alwaysUsedPresets
],
plugins: [...alwaysUsedPlugins],
}
: {
/**
* Legacy build
*/
presets: [
presetEnv,
...alwaysUsedPresets
],
plugins: [
...alwaysUsedPlugins,
...legacyPlugins
],
};
const developmentConfig =
modern === "modern"
? {
/**
* Modern build
*/
presets: [
presetModule,
...alwaysUsedPresets
],
plugins: [
...alwaysUsedPlugins
],
}
: {
/**
* Legacy build
*/
presets: [
presetEnv,
...alwaysUsedPresets
],
plugins: [
...alwaysUsedPlugins,
...legacyPlugins
],
};
return {
env: {
production: productionConfig,
development: developmentConfig,
test: {
/**
* Chances are tests will run in node
**/
presets: [
"@babel/preset-env",
...alwaysUsedPresets
],
plugins: [
...alwaysUsedPlugins,
...legacyPlugins
],
},
},
};
};
babel이 비동기적으로 로드될 때만 작동하기 때문에 .mjs 대안을 사용하지 않았습니다.
ROLLUP_BUILD_TYPE
은 preset-modules
보다 적은 코드를 트랜스파일합니다. 이유를 이해하려면 the documentation을 읽으십시오.이제 번들이 있으므로 타겟에 로드할 방법이 필요합니다.
모듈/노모듈 패턴
이 기술(2017에서)은 레거시 브라우저(요즘 대부분 IE)와 "에버그린"브라우저(Chrome, Firefox, Safari, Edge 등) 간의 중단점으로
preset-env
지원을 활용합니다.이를 통해 최신 번들을 최신 브라우저에 보내고 레거시 번들을 이전 브라우저에 보낼 수 있습니다.
오랫동안 일이 그렇게 간단하지 않았습니다. 이것은 이제 삭제되었으며
<script type="module">
을 안전하게 사용할 수 있습니다.패턴:
<script type="module">
import("/js/esm/main.js").then((module) => {
/** ... **/
});
</script>
<script nomodule src="/js/legacy/main.js"></script>
미래
이 게시물은 ES2017에 관한 것이지만 브라우저 지원이 계속 유지되는 한 여기에 설명된 기술을 나중에 업데이트하여 최신 버전의 언어를 사용할 수 있습니다.
주목해야 할 중요한 제한 사항 중 하나는 대부분의 타사 라이브러리가 여전히 don't export untranspiled code 이라는 것입니다. 불행히도 이것은 당신이 제공하는 대부분의 코드가 현재로서는 여전히 ES5라는 것을 의미합니다.
그러나 Babel 구성에서 node_modules/제외를 중단하고 더 많은 사람들이 동일한 작업을 수행하면 상황이 곧 개선될 수 있습니다.
Reference
이 문제에 관하여(롤업으로 최신 JavaScript 제공), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/camillehdl/ship-modern-javascript-with-rollup-2e8a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)