前言:承接之前的webpack學習,請看完入門筆記1後再看本章內容
第 7 章:Webpack 配置詳情
7.1 entry
entry: 入口起點
- string --> './src/index.js',單入口
打包形成一個 chunk。 輸出一個 bundle 文件。此時 chunk 的名稱默認是 main - array --> ['./src/index.js', './src/add.js'],多入口
所有入口文件最終只會形成一個 chunk,輸出出去只有一個 bundle 文件。
(一般只用在 HMR 功能中讓 html 熱更新生效) - object,多入口
有幾個入口文件就形成幾個 chunk,輸出幾個 bundle 文件,此時 chunk 的名稱是 key 值
--> 特殊用法:
1 entry: { 2 // 最終只會形成一個chunk, 輸出出去只有一個bundle文件。 3 index: ['./src/index.js', './src/count.js'], 4 // 形成一個chunk,輸出一個bundle文件。 5 add: './src/add.js' 6 }
7.2 output
1 output: { 2 // 文件名稱(指定名稱+目錄) 3 filename: 'js/[name].js', 4 // 輸出文件目錄(將來所有資源輸出的公共目錄) 5 path: resolve(__dirname, 'build'), 6 // 所有資源引入公共路徑前綴 --> 'imgs/a.jpg' --> '/imgs/a.jpg' 7 publicPath: '/', 8 chunkFilename: 'js/[name]_chunk.js', // 指定非入口chunk的名稱 9 library: '[name]', // 打包整個庫後向外暴露的變量名 10 libraryTarget: 'window' // 變量名添加到哪個上 browser:window 11 // libraryTarget: 'global' // node:global 12 // libraryTarget: 'commonjs' // conmmonjs模塊 exports 13 },
7.3 module
1 module: { 2 rules: [ 3 // loader的配置 4 { 5 test: /\.css$/, 6 // 多個loader用use 7 use: ['style-loader', 'css-loader'] 8 }, 9 { 10 test: /\.js$/, 11 // 排除node_modules下的js文件 12 exclude: /node_modules/, 13 // 只檢查src下的js文件 14 include: resolve(__dirname, 'src'), 15 enforce: 'pre', // 優先執行 16 // enforce: 'post', // 延後執行 17 // 單個loader用loader 18 loader: 'eslint-loader', 19 options: {} // 指定配置選項 20 }, 21 { 22 // 以下配置只會生效一個 23 oneOf: [] 24 } 25 ] 26 },
7.4 resolve
1 // 解析模塊的規則 2 resolve: { 3 // 配置解析模塊路徑別名: 優點:當目錄層級很複雜時,簡寫路徑;缺點:路徑不會提示 4 alias: { 5 $css: resolve(__dirname, 'src/css') 6 }, 7 // 配置省略文件路徑的後綴名(引入時就可以不寫文件後綴名了) 8 extensions: ['.js', '.json', '.jsx', '.css'], 9 // 告訴 webpack 解析模塊應該去找哪個目錄 10 modules: [resolve(__dirname, '../../node_modules'), 'node_modules'] 11 }
這樣配置後,引入文件就可以這樣簡寫:import '$css/index';
7.5 dev server
1 devServer: { 2 // 運行代碼所在的目錄 3 contentBase: resolve(__dirname, 'build'), 4 // 監視contentBase目錄下的所有文件,一旦文件變化就會reload 5 watchContentBase: true, 6 watchOptions: { 7 // 忽略文件 8 ignored: /node_modules/ 9 }, 10 // 啓動gzip壓縮 11 compress: true, 12 // 端口號 13 port: 5000, 14 // 域名 15 host: 'localhost', 16 // 自動打開瀏覽器 17 open: true, 18 // 開啓HMR功能 19 hot: true, 20 // 不要顯示啓動服務器日誌信息 21 clientLogLevel: 'none', 22 // 除了一些基本信息外,其他內容都不要顯示 23 quiet: true, 24 // 如果出錯了,不要全屏提示 25 overlay: false, 26 // 服務器代理,--> 解決開發環境跨域問題 27 proxy: { 28 // 一旦devServer(5000)服務器接收到/api/xxx的請求,就會把請求轉發到另外一個服務器3000 29 '/api': { 30 target: 'http://localhost:3000', 31 // 發送請求時,請求路徑重寫:將/api/xxx --> /xxx (去掉/api) 32 pathRewrite: { 33 '^/api': '' 34 } 35 } 36 } 37 }
其中,跨域問題:同源策略中不同的協議、端口號、域名就會產生跨域。
正常的瀏覽器和服務器之間有跨域,但是服務器之間沒有跨域。代碼通過代理服務器運行,所以瀏覽器和代理服務器之間沒有跨域,瀏覽器把請求發送到代理服務器上,代理服務器替你轉發到另外一個服務器上,服務器之間沒有跨域,所以請求成功。代理服務器再把接收到的響應響應給瀏覽器。這樣就解決開發環境下的跨域問題。
7.6 optimization
contenthash 緩存會導致一個問題:修改 a 文件導致 b 文件 contenthash 變化。
因爲在 index.js 中引入 a.js,打包後 index.js 中記錄了 a.js 的 hash 值,而 a.js 改變,其重新打包後的 hash 改變,導致 index.js 文件內容中記錄的 a.js 的 hash 也改變,從而重新打包後 index.js 的 hash 值也會變,這樣就會使緩存失效。(改變的是a.js文件但是 index.js 文件的 hash 值也改變了)
解決辦法:runtimeChunk --> 將當前模塊記錄其他模塊的 hash 單獨打包爲一個文件 runtime,這樣 a.js 的 hash 改變只會影響 runtime 文件,不會影響到 index.js 文件
1 output: { 2 filename: 'js/[name].[contenthash:10].js', 3 path: resolve(__dirname, 'build'), 4 chunkFilename: 'js/[name].[contenthash:10]_chunk.js' // 指定非入口文件的其他chunk的名字加_chunk 5 }, 6 optimization: { 7 splitChunks: { 8 chunks: 'all', 9 /* 以下都是splitChunks默認配置,可以不寫 10 miniSize: 30 * 1024, // 分割的chunk最小爲30kb(大於30kb的才分割) 11 maxSize: 0, // 最大沒有限制 12 minChunks: 1, // 要提取的chunk最少被引用1次 13 maxAsyncRequests: 5, // 按需加載時並行加載的文件的最大數量爲5 14 maxInitialRequests: 3, // 入口js文件最大並行請求數量 15 automaticNameDelimiter: '~', // 名稱連接符 16 name: true, // 可以使用命名規則 17 cacheGroups: { // 分割chunk的組 18 vendors: { 19 // node_modules中的文件會被打包到vendors組的chunk中,--> vendors~xxx.js 20 // 滿足上面的公共規則,大小超過30kb、至少被引用一次 21 test: /[\\/]node_modules[\\/]/, 22 // 優先級 23 priority: -10 24 }, 25 default: { 26 // 要提取的chunk最少被引用2次 27 minChunks: 2, 28 prority: -20, 29 // 如果當前要打包的模塊和之前已經被提取的模塊是同一個,就會複用,而不是重新打包 30 reuseExistingChunk: true 31 } 32 } */ 33 }, 34 // 將index.js記錄的a.js的hash值單獨打包到runtime文件中 35 runtimeChunk: { 36 name: entrypoint => `runtime-${entrypoint.name}` 37 }, 38 minimizer: [ 39 // 配置生產環境的壓縮方案:js/css 40 new TerserWebpackPlugin({ 41 // 開啓緩存 42 cache: true, 43 // 開啓多進程打包 44 parallel: true, 45 // 啓用sourceMap(否則會被壓縮掉) 46 sourceMap: true 47 }) 48 ] 49 }
第 8 章:webpack5
此版本重點關注以下內容:
- 通過持久緩存提高構建性能.
- 使用更好的算法和默認值來改善長期緩存.
- 通過更好的樹搖和代碼生成來改善捆綁包大小.
- 清除處於怪異狀態的內部結構,同時在 v4 中實現功能而不引入任何重大更改.
- 通過引入重大更改來爲將來的功能做準備,以使我們能夠儘可能長時間地使用 v5.
1.下載
- npm i webpack@next webpack-cli -D
2.自動刪除 Node.js Polyfills
早期,webpack 的目標是允許在瀏覽器中運行大多數 node.js 模塊,但是模塊格局發生了變化,許多模塊用途現在主要是爲前端目的而編寫的。webpack <= 4 附帶了許多 node.js 核心模塊的 polyfill,一旦模塊使用任何核心模塊(即 crypto 模塊),這些模塊就會自動應用。
儘管這使使用爲 node.js 編寫的模塊變得容易,但它會將這些巨大的 polyfill 添加到包中。在許多情況下,這些 polyfill 是不必要的。webpack 5 會自動停止填充這些核心模塊,並專注於與前端兼容的模塊。
遷移:
- 儘可能嘗試使用與前端兼容的模塊。
- 可以爲 node.js 核心模塊手動添加一個 polyfill。錯誤消息將提示如何實現該目標。
3.Chunk 和模塊 ID
添加了用於長期緩存的新算法。在生產模式下默認情況下啓用這些功能。
chunkIds: "deterministic", moduleIds: "deterministic"
Chunk ID
你可以不用使用 import(/* webpackChunkName: "name" */ "module")
在開發環境來爲 chunk 命名,生產環境還是有必要的
webpack 內部有 chunk 命名規則,不再是以 id(0, 1, 2)命名了
4.Tree Shaking
- webpack 現在能夠處理對嵌套模塊的 tree shaking
1 // inner.js 2 export const a = 1; 3 export const b = 2; 4 5 // module.js 6 import * as inner from './inner'; 7 export { inner }; 8 9 // user.js 10 import * as module from './module'; 11 console.log(module.inner.a);
在生產環境中, inner 模塊暴露的 b
會被刪除
- webpack 現在能跟多個模塊之前的關係
1 import { something } from './something'; 2 3 function usingSomething() { 4 return something; 5 } 6 7 export function test() { 8 return usingSomething(); 9 }
當設置了"sideEffects": false
時,一旦發現test
方法沒有使用,不但刪除test
,還會刪除"./something"
- webpack 現在能處理對 Commonjs 的 tree shaking
5.Output
webpack 4 默認只能輸出 ES5 代碼
webpack 5 開始新增一個屬性 output.ecmaVersion, 可以生成 ES5 和 ES6 / ES2015 代碼.
如:output.ecmaVersion: 2015
6.SplitChunk
1 // webpack4 2 minSize: 30000; 3 4 5 // webpack5 6 minSize: { 7 javascript: 30000, 8 style: 50000, 9 }
7.Caching
1 // 配置緩存 2 cache: { 3 // 磁盤存儲 4 type: "filesystem", 5 buildDependencies: { 6 // 當配置修改時,緩存失效 7 config: [__filename] 8 } 9 }
緩存將存儲到 node_modules/.cache/webpack
8.監視輸出文件
之前 webpack 總是在第一次構建時輸出全部文件,但是監視重新構建時會只更新修改的文件。
此次更新在第一次構建時會找到輸出文件看是否有變化,從而決定要不要輸出全部文件。
9.默認值
entry: "./src/index.js
output.path: path.resolve(__dirname, "dist")
output.filename: "[name].js"
其他
webpack官網:https://www.webpackjs.com/concepts/
其他優秀的webpack推薦:Webpack4不求人系列(共5篇)