webpack@5ã®ä¸»ãªå¤æ´ç¹ã¾ã¨ã
äºå®ã§ã¯ãææ¥ã®10æ¥ã«webpackã®ã¡ã¸ã£ã¼ãã¼ã¸ã§ã³ã§ããv5ããªãªã¼ã¹ããã¾ãããã¾ã ã¨ã³ã·ã¹ãã ãå®å®ãã¦ããªãå¯è½æ§ãããããã注æãã¦ã¢ããã°ã¬ã¼ããè¡ã£ã¦ãã ããã
change log:
移è¡ã¬ã¤ã:
- 追å æ©è½
- Persistent Caching
- Module Federation
- assetModules typeã®è¿½å
- ãã£ã³ã¯åãIDã¸å¤æ´
- import.metaã®ãµãã¼ã
- data, file, http(s)ã®ãããã³ã«ã®ãµãã¼ã
- Native Workerã®ãµãã¼ã
- publicPathã®èªåå
- Tree Shakingã®æé©å
- output.filename, output. chunkFilenameã®é¢æ°å
- externalsTypeã®è¿½å
- targetã®è©³ç´°åã¨browserslistã®ãµãã¼ã
- TypeScriptåå®ç¾©ãã¡ã¤ã«ã®æä¾
- splitChunksã§ã®ãµã¤ãºè¨å®å¤ã®å¤æ´
- å®é¨ç段é
- ç ´å£çå¤æ´
追å æ©è½
Persistent Caching
ãã®ãã¼ã¸ã§ã³ããã¯ä»ã¾ã§ã¡ã¢ãªä¸ã§ããè¡ã£ã¦ãªãã£ããã¡ã¤ã«ã·ã¹ãã ã«ãããã£ãã·ã¥ãå°å ¥ããã¾ãã以ä¸ã®ããã«è¨å®ãããã¨ã«ãããå¤§å¹ ãªé度æ¹åãè¦è¾¼ãã¾ãã
module.exports = { cache: { type: 'filesystem', buildDependencies: { config: [__filename] } } };
ãªã â
asset main.js 36.3 KiB [emitted] [minimized] (name: main) orphan modules 584 KiB [orphan] 554 modules cacheable modules 117 KiB ./src/index.js + 103 modules 117 KiB [built] [code generated] ./src/foo.js 21 bytes [built] [code generated] webpack 5.0.0-rc.2 compiled successfully in 1836 ms
ããâ
asset main.js 36.3 KiB [compared for emit] [minimized] (name: main) cached modules 700 KiB [cached] 556 modules webpack 5.0.0-rc.2 compiled successfully in 429 ms
詳ããã¯ä»¥ä¸ã®è¨äºãåç §ã«ãã¦ãã ããã
Module Federation
ãªãã¸ããªé(ãã³ãã«é)ãè·¨ãã¨ãã«ã©ã¤ãã©ãªãªã©ã®éè¤ãã¦ããã³ã¼ãã以ä¸ã®ããã«å¹çããæ±ããã³ãã«ãµã¤ãºãä¸ããä»çµã¿ã§ãããã®æ©è½ã¯ãäºãã®webpackã¨é£æºãåãåãå¿ è¦ãããããäºãã«webpack@5ã§ããå¿ è¦ãããã¾ãã
詳ããã¯ä»¥ä¸ã®è¨äºãåèã«ãã¦ãã ããã
assetModules typeã®è¿½å
ä»ã¾ã§ç»åãªã©ãèªã¿è¾¼ãã¨ãã«ãfile-loaderãurl-loader, raw-loaderãªã©ã使ã£ã¦ãã¾ãããããããã¤ãã£ããµãã¼ãããã¾ããã
module.exports = { output: { assetModuleFilename: 'images/[hash][ext]', }, module: { rules: [ { test: /\.(png|jpg|gif)$/, type: 'asset/resource' } ] } };
詳ããã¯ä»¥ä¸ã®è¨äºãåèã«ãã¦ãã ããã
ãã£ã³ã¯åãIDã¸å¤æ´
ä»ã¾ã§ä»¥ä¸ã®ããã«webpackChunkName
ã¨æ¸ããªããã°èªããªããã¡ã¤ã«åã¨ãªã£ã¦ãã¾ãããã人ãèªããå½¢ã¨ãªãã¾ããããã«ä¼´ããéçºä¸ã§ã®webpackChunkName
ã®æå®ãããå¿
è¦ããªããªããã¨ãæå¾
ããã¾ãã
(async () => { await import(/* webpackChunkName: "foo" */ './foo'); })();
ååãã¤ããã¨ãã®åºå
asset main.js 2.79 KiB [emitted] [minimized] (name: main) asset foo.js 114 bytes [emitted] [minimized] (name: foo) runtime modules 7.23 KiB 10 modules cacheable modules 217 bytes ./src/index.js 190 bytes [built] [code generated] ./src/foo.js 27 bytes [built] [code generated] webpack 5.0.0-rc.4 compiled successfully in 274 ms
v5ã®ããã©ã«ãã§ã¯ä»¥ä¸ã®ããã«deterministic
ã¨ããè¨å®ã®æ°ããã¢ã«ã´ãªãºã ã追å ãããã¢ã¸ã¥ã¼ã«/ãã£ã³ã¯ã®ååã«3~4æ¡ã®æ°å¤IDãä»ä¸ãããããã«ãªãã¾ããããã«ãããããã·ã¥åãããã¢ã¸ã¥ã¼ã«IDã«ããgzipã§ã®ããã©ã¼ãã³ã¹ä½ä¸ã¯ä¿®æ£ããã¾ããã
asset main.js 2.79 KiB [emitted] [minimized] (name: main) asset 717.js 114 bytes [emitted] [minimized] runtime modules 7.23 KiB 10 modules cacheable modules 186 bytes ./src/index.js 159 bytes [built] [code generated] ./src/foo.js 27 bytes [built] [code generated] webpack 5.0.0-rc.4 compiled successfully in 283 ms
ãã¡ã¤ã«åãèªåçã«ä»ä¸ãããå ´å
module.exports = { optimization: { chunkIds: 'named' } };
asset main.js 2.8 KiB [emitted] [minimized] (name: main) asset src_foo_js.js 123 bytes [emitted] [minimized] runtime modules 7.23 KiB 10 modules cacheable modules 186 bytes ./src/index.js 159 bytes [built] [code generated] ./src/foo.js 27 bytes [built] [code generated] webpack 5.0.0-rc.4 compiled successfully in 256 ms
optimization.chunkIds
ã« named
ã追å ããã°ãã¡ã¤ã«åã確å®ãã¾ããæ¬çªç°å¢ã§ã¯è¡¨ç¤ºããã¦ãããã®ãªã®ããæ¤è¨ãã¦ãã ãããã¾ããoptimization.splitChunks.name
ã¯ãªããªã£ãã®ã§ãã¡ãã«ç§»è¡ãã¦ãã ããã
import.metaã®ãµãã¼ã
// ./src/index.js console.log(import.meta.url); console.log(import.meta.webpack);
// ./dist/main.js // çæããããã¡ã¤ã«ã¯åºå®å¤ã¨ãã¦å ¥ããimport.meta.url, webpackã¯åå¨ããªããªã console.log("file:///Users/hiroppy/webpack/src/index.js"); console.log(5);
ã¾ããHMRæã«ä»ã¾ã§ã¯ä»¥ä¸ã®ããã«æ¸ãã¦ãã¾ããããããããã¯import.meta.webpackHot
ã使ããã¨ãå¯è½ã§ããããã使ããã¨ã«ãããNode.jsã®moduleã¸ã®ä¾åãæ¸ãããESMã«æ²¿ããããªæ¸ãæ¹ã«å¤ããã¾ãã
// <= 4 if (module.hot) { module.hot.accept(); } // >= 5 if(import.meta.webpackHot) { import.meta.webpackHot.accept(); } // or import.meta.webpackHot?.accept();
data
, file
, http(s)
ã®ãããã³ã«ã®ãµãã¼ã
import x from 'data:text/javascript,export default 42'; console.log(x); // 42 import y from 'file:///Users/hiroppy/webpack/src/index.js';
ã¾ãããã©ã°ã¡ã³ã(#
)ããµãã¼ãããã¾ããã
const eIndexOf = require('es5-ext/array/\0#/e-index-of#fragment');
http(s)ãããã³ã«ã¯ãã¾ã å®å ¨ã«ãµãã¼ãããã¦ããªããã以ä¸ã®è¨å®ãå¿ è¦ã§ãã
const webpack = require('webpack'); module.exports = { plugins: [ new webpack.experiments.schemes.HttpUriPlugin(), new webpack.experiments.schemes.HttpsUriPlugin() ] }; // index.js import codeOfConduct from 'https://raw.githubusercontent.com/webpack/webpack/master/CODE_OF_CONDUCT.md'; console.log(codeOfConduct);
Native Workerã®ãµãã¼ã
new Worker(new URL('...', import.meta.url))
ãWebWorkerãä½ãããã«ãµãã¼ãããã¾ãããããã¯SharedWorkerãåæ§ã§ãã
const fooWorker = new SharedWorker(new URL("./foo-worker.js", import.meta.url), { name: 'foo' });
publicPathã®èªåå
æ°ããããã©ã«ãå¤ã¨ãã¦auto
ã追å ãããdocument.currentScript
, document.getElementsByTagName('script')
, self.location
ã®ä¸ããèªåçã«æ±ºå®ããã¾ãã注æç¹ã¨ãã¦ãIEã§ã¯document.currentScript
ããµãã¼ãããã¦ããªããããdeferred ã async ã®ã¹ã¯ãªããã«ã¯ä½¿ç¨ãããã¨ãã§ãã¾ããã
module.exports = { output: { publicPath: 'auto' } };
Tree Shakingã®æé©å
ãã¹ããããã¢ã¸ã¥ã¼ã«ã®å ´åãä»ã¾ã§ã¯ä½¿ããã¦ããªãb
ã¯åé¤ã§ãã¾ããã§ãããv5ããã¯è¿½è·¡å¯è½ã¨ãªãã§ããããã«ãªãã¾ããã
// inner.js export const a = 1; export const b = 2; // module.js import * as inner from "./inner"; export { inner } // user.js import * as module from "./module"; console.log(module.inner.a);
v4ã§ã¯ãã¢ã¸ã¥ã¼ã«ã®é¢ä¿æ§ããè¦ã¦ãã¾ããã§ããããv5ããå
¥ã£ãoptimization.innerGraph
ã«ãããå
é¨ã¢ã¸ã¥ã¼ã«ã¸ã®æé©åãè¡ããããã«ãªãã¾ããã
import { something } from "./something"; function usingSomething() { return something; } export function test() { return usingSomething(); }
以ä¸ã®ã±ã¼ã¹ã対象ã§ãã
- é¢æ°å®£è¨
- ã¯ã©ã¹å®£è¨
- å¤æ°å®£è¨ åã³
export default
Optimization.sideEffects
ã§ã¯ãã½ã¼ã¹ã³ã¼ãããå¯ä½ç¨ã®ãªãã¢ã¸ã¥ã¼ã«ã®åç´ãªã±ã¼ã¹ãæ¤åºã§ããããã«ãªãã¾ãããã¯ã©ã¹ããã³é¢æ°å®£è¨ãç°¡åãªinitå¼ã使ç¨ããå¤æ°å®£è¨ãif
ãwhile
ãfor
ãswitch
ãexport
ãimport
ãç°¡åãªãã©ã°ã使ç¨ããé¢æ°å¼ã³åºã çã§ãã
ã¾ããCJSããµãã¼ãããã¾ããã
module.exports = require('...')
module.exports.a.b.c = require('...').a.b.c
Object.defineProperty(module.exports, 'xxx', ...)
require('abc').xxx
ãã®ãµãã¼ãã¯ãESMãCJSéã§ãåãã®ã§ãä»å¾ã©ã¡ãã®ã¢ã¸ã¥ã¼ã«ã·ã¹ãã ã使ã£ã¦ããããæ°ã«ããã«æé©åè¡ããããã«ãªãã¾ãã
ããã¯å¥ã®è¨äºã§è©³ç´°ã«èª¬æããã®ã§äºå®ã§ãã
output.filename, output. chunkFilenameã®é¢æ°å
output.filename
ã¯ä»ã¾ã§æååããåãåãã¾ããã§ããããé¢æ°ã«ãããã¨ãå¯è½ã¨ãªã£ãããæ´ã«æè»ãªè¨å®ã表ç¾ãããã¨ãå¯è½ã¨ãªãã¾ãã
module.exports = { output: { filename: ({ chunk }) => { if (chunk.name === 'main') return 'main.bundle.[contenthash].js'; return 'foo.bundle.[contenthash].js' } } };
externalsTypeã®è¿½å
externalsType
ã«promise
, import
, script
ã追å ãããããæè»ã«å¯¾å¿ã§ããããã«ãªãã¾ããã
- promise:
var
ã¨åæ§ã ããéåæã¢ã¸ã¥ã¼ã«ã¨ãªã - import:
import()
ã使ããéåæã®ãã¤ãã£ãESMã¢ã¸ã¥ã¼ã«ãèªã¿è¾¼ã - script:
<script>
ã使ããäºåã«å®ç¾©ãããã°ãã¼ãã«å¤æ°ãå ¬éããã¹ã¯ãªãããèªã¿è¾¼ã
module.exports = { externalsType: 'promise' };
targetã®è©³ç´°åã¨browserslistã®ãµãã¼ã
target
ã«å¯¾ãã¦ã詳細ãªè¨å®ãã§ããããã«ãªãã¾ããã é
åãåãåãããã«ãªããtarget: ['web', 'es2015']
çã®æ¸ãæ¹ãè¡ããããã«ãªãã¾ããã ã¾ããbrowserslistãããããããweb
ã®å ´åã¯target
ã®è¨å®ã¯ä¸è¦ã¨ãªãã¾ãã
ããã©ã«ãå¤ã¯target: 'browserslist'
ã¨ãªãããã©ã¼ã«ããã¯å
ã¯å¤ãããã«web
ã¨ãªãã¾ãã
TypeScriptåå®ç¾©ãã¡ã¤ã«ã®æä¾
@types/webpack
ã¯ä¸è¦ã«ãªãã¾ããã
import { WebpackOptionsNormalized } from 'webpack'; const config: WebpackOptionsNormalized = { entry: 'index.js', output: { filename: 'bundle.js' } };
splitChunksã§ã®ãµã¤ãºè¨å®å¤ã®å¤æ´
ä»ã¾ã§ã¯ãJSã®ã¿ã®ãã£ã³ã¯ãµã¤ãºã§ããããããã«è©³ç´°ã«æå®ã§ããããã«ãªãã¾ããã
module.exports = { optimization: { splitChunks: { cacheGroups: { test: { name: 'test', minSize: { javascript: 100, webassembly: 100, style: 100, } } } } } };
ã¾ããæ¬çªç°å¢ã§ã®minSize
ã®ããã©ã«ãå¤ã¯20k
ã¨ãªãã¾ããã
å®é¨ç段é
top-level-awaitã®ãµãã¼ã
ã·ã³ã¿ãã¯ã¹ã¯ESMã®ä»æ§ã«æ²¿ãã¾ãããã¾ã stage-3ãªã®ã§å®é¨çãã§ã¼ãºã§ãã
// webpack.config.js module.exports = { experiments: { topLevelAwait: true, } };
const x = await import('file:///Users/hiroppy/Desktop/webpack-5/src/foo.js'); console.log(x);
scriptã¿ã°ã§ã®ã¢ã¸ã¥ã¼ã«ãµãã¼ã
ãã³ãã«æã«ä½¿ãããIIFEãåãé¤ããã<script type="module">
çµç±ã§å¼ã³åºãããå½¢ã«åºåããã¾ãããã®å ´åãä»æ§ã«æ²¿ãå³æ ¼ã¢ã¼ãã¨é
延ãã¼ããæå¹åããã¾ãã
module.exports = { experiments: { outputModule: true } };
ç ´å£çå¤æ´
æä½è¦æ±ãã¼ã¸ã§ã³ãNode.js@10ã¸
webpackåã³webpackã®ã³ã¢ã«ãããã¨ã³ã·ã¹ãã ãè¦æ±ããNode.jsã®ãã¼ã¸ã§ã³ã®æä½å¤ã¯10ã¨ãªãã¾ãã
Node.jsã®polyfillã®èªåæ¿å ¥ãå»æ¢
ã¡ã³ãã¼éã§ãè³å¦ä¸¡è«ãããã¾ããããçç±ã¨ãã¦ã¯ä»¥ä¸ã®ãããªç®çãããã¾ãã
- webpackã¯webã¸åãã£ã¦ãã
- polyfillèªä½ãå®å ¨äºæãªãã®ã§ã¯ãªã
- ã¡ã³ããã³ã¹ã³ã¹ãã®é«ã
èªåãçµé¨ããä¾ã¨ãã¦ã¯ãprocess
ãutil
ã«ä¾åãã¦ããNode.jsã®ã³ã¼ããã¯ã©ã¤ã¢ã³ããµã¤ãã§ä½¿ãå ´åããããv5ã«ä¸ãããåããªããªãå ´åãããã¾ãã
å®éã«webpack4ã¾ã§ä½¿ã£ã¦ããpolyfillã¯ä»¥ä¸ã®ãªãã¸ããªã§ç®¡çããã¦ããã®ã§ããããåèã«ãã¦åèªã§è¿½å ããå¿ è¦ãããã¾ãã
ããã«ä¼´ããnode.*
ã®ä¸ã®ãã¤ãã£ãã¢ã¸ã¥ã¼ã«ããã¹ã¦å»æ¢ã¨ãªãã¾ãã ã¾ããglobal
, __filename
, __dirname
ã¯ããã©ã«ãã§false
ã®å¤ã¨ãªãã¾ãã
module.exports = { node: { // Buffer: false, ããã¯å»æ¢ global: false, __filename: false, __dirname: false, } };
JSONã§ã®named exportã®ç¦æ¢
ESMã®ä»æ§ä¸ãããã¯è¨±å¯ããã¦ããªããããããè¡ããã¦ããã³ã¼ãã®å ´åè¦åãåºãããã«ãªãããã以ä¸ã®ããã«å¤æ´ããå¿ è¦ãããã¾ãã
// ðµ import { version } from './package.json'; // ð import package from './package.json'; const { version } = package;
loaderã¨useã®éããå³æ ¼å
rules.loader
ã¨rules.use
ã§ç®çã«åã£ã¦ãªã使ãæ¹ã®è¨å®ã®å ´åãã¨ã©ã¼ãåãããã«ãªãã¾ããã use
ã¯options
ããªãå ´åã®ã¿ä½¿ç¨å¯è½(å¼æ°ã¯åãå
¥ãå¯)ã¨ãªããoptions
ãããå ´åã¯loader
ã使ããªããã°ãªãã¾ããã
ç´°ããå¤æ´ã§ãããã¦ã¼ã¶ã¼ã¸ã®å½±é¿ã大ãããã®ã®ä¸ã¤ã¨ãã¦ãwebpack@5ã§ã¯ä»¥ä¸ã®ãããªã«ã¼ã«ã¨ãªããè¨å®ãã¡ã¤ã«ã®ã¨ã©ã¼ã¨ãªããå®è¡ã§ããªããªãã¾ãã
— è丸ãã¡ã³ (@about_hiroppy) 2020å¹´9æ14æ¥
use -> optionsããªãå ´åã®ã¿ä½¿ç¨å¯è½(å¼æ°ã¯åãå ¥ãå¯)
loader -> loaderã«å¼æ°ãä»ããå ´åãuseã«å¤æ´ããããã« pic.twitter.com/qqmsoWWzWn
ããã©ã«ãã©ã³ã¿ã¤ã ãä¸é¨ES2015ã¸å¤æ´
webpackã®çæããã³ã¼ãã®ããã©ã«ããä¸é¨es5ãães2015ã¨ãªãã¾ãã
ããã¯ããã¾ã§ããã³ãã«ãµã¤ãºãæ¸ãããã¨ãç®çãªãããvar
ããconst
ã«ã¯ãªã£ãããããfunction
ã() => {}
ã¨ãªãã¾ãã
ããIEããµãã¼ããã¦ããå ´åã¯ä»¥ä¸ã追å ããå¿
è¦ãããã¾ãã
module.exports = { target: ['web', 'es5'] };
ã¾ããããã¯è¿½å æ©è½ã¨ãã¦ç¨æãããbrowserslistãç¨ãã¦åé¿ãããã¨ãå¯è½ã§ãã
# browserslist last 1 version