webpack4.x常用配置
- 2020 年 1 月 13 日
- 筆記
打包多頁面在git倉庫里,並沒有單獨寫出來。
初始化:
yarn init -y
yarn add webpack webpack-cli -D
webpack-cli的作用就是讓我們能在命令行中使用
webpack
、npx webpakck
這些指令。
webpack基礎配置
// webpack 是node寫出來,所以要按node的寫法 const path = require('path'); module.exports = { mode: 'development', // 模式 默認值:production [development] entry: './src/index.js', // 打包入口文件 output: { filename: 'bundle.[hash:8].js', // 打包後的文件名 path: path.resolve(__dirname, 'dist') // 這個路徑必須是一個絕對路徑,所以需要用path來解析一下 } }
// src/index.js console.log('hello webpack4.0');
npx webpack
命令直接打包(npm5.2之後支援的語法)。會打包出一個main.js
文件
默認支援js模組化:
// commonjs // src/a.js module.exports = 'FinGet' // src/index.js let name = require('./a.js'); console.log(name); // 'FinGet'
// ES6 module // src/a.js export default = 'FinGet' // src/index.js import name from './a.js' console.log(name); // 'FinGet'
手動配置webpack
- 默認配置文件的名字:
webpack.config.js
。為啥叫這個名字呢?
// node_modules/webpack-cli/bin/config/config-yargs.js ... module.exports = function(yargs) { yargs .help("help") .alias("help", "h") .version() .alias("version", "v") .options({ config: { type: "string", describe: "Path to the config file", group: CONFIG_GROUP, defaultDescription: "webpack.config.js or webpackfile.js", // 默認名字有兩種 requiresArg: true }, ...
- 可以通過–config指定配置文件: npx webpack –config xxxx.js
- 也可以在
package.json
中配置腳本
"script": { "build": "webpack --config webpack.config.my.js" },
運行 npm run build
- 如果在
package.json
中不設置config文件
"script": { "build": "webpack" },
運行 npm run build -- --config webpack.config.my.js
--
不能少!
- 簡化的webpack打包出來的文件:
(function(modules) { // webpackBootstrap // The module cache 先定義一個快取 var installedModules = {}; // The require function 配置了一個require方法 function __webpack_require__(moduleId) { // Check if module is in cache 檢查這個模組是否在快取中 if (installedModules[moduleId]) { return installedModules[moduleId].exports; } // Create a new module (and put it into the cache) 創建一個新的模組,並存入快取 var module = installedModules[moduleId] = { i: moduleId, l: false, exports: {} }; // Execute the module function modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); // Flag the module as loaded module.l = true; // Return the exports of the module return module.exports; } // Load entry module and return exports 載入入口模組 return __webpack_require__(__webpack_require__.s = "./src/index.js"); })({ // key-value key -> 模組路徑 | value -> 函數 "./src/a.js": (function(module, exports) { eval("module.exports="FinGet";nn//# sourceURL=webpack:///./src/a.js?"); }), "./src/index.js": (function(module, exports, __webpack_require__) { eval("let name = __webpack_require__(/*! ./a.js */ "./src/a.js");nconsole.log('hello webpack4.0');nconsole.log(name);nn//# sourceURL=webpack:///./src/index.js?"); }) });
webpack-dev-server
yarn add webpack-dev-server -D
它會在記憶體中生成打包文件。
官方文檔: https://webpack.docschina.org/configuration/dev-server/
本地服務
// webpack.config.js // 開發伺服器的配置 官方文檔: https://webpack.docschina.org/configuration/dev-server/ devServer: { contentBase: './dist', // 告訴伺服器從哪個目錄中提供內容。只有在你想要提供靜態文件時才需要。 publicPath: './dist', // 將用於確定應該從哪裡提供 bundle,並且此選項優先。 此路徑下的打包文件可在瀏覽器中訪問。 port: 3000, // 埠 progress: true, // 打包過程 open: true, // 自動打開瀏覽器 compress: true, // 一切服務都啟用 gzip 壓縮 // host: '' , // 指定使用一個 host hot: true, // 啟用 webpack 的 模組熱替換 功能 依賴於HotModuleReplacementPlugin } plugins: [ // 開啟webpack全局熱更新 new webpack.HotModuleReplacementPlugin() ]
做代理
devServer : { proxy: { // 代理 '/api': { target: 'http://localhost:3000', pathRewrite: {'^/api' : ''} } } }
mock數據
devServer: { // 前端mock數據 不存在跨域 before(app) { app.get('/api/goods', (req, res) => { res.json({ code: 0, list: [ {id:1,name:'蘋果'}, {id:2,name:'香蕉'} ] }) }) } }
html-webpack-plugin
yarn add html-webpack-plugin -D
plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname,'./public/index.html'), // 模版路徑 filename: 'index.html', // 打包後的文件名 title: 'webpack4.0', // 顧名思義,設置生成的 html 文件的標題 /** 注入選項。有四個選項值 true, body, head, false true 默認值,script標籤位於html文件的 body 底部body 同 true head script 標籤位於 head 標籤內 false 不插入生成的 js 文件,只是單純的生成一個 html 文件 */ inject: true, // favicon: 'xxx.ico' // 給生成的 html 文件生成一個 favicon minify: { // 壓縮 removeAttributeQuotes: true, // 去掉屬性的雙引號 collapseWhitespace: true // 程式碼壓縮成一行 }, hash: true, // hash選項的作用是 給生成的 js 文件一個獨特的 hash 值,該 hash 值是該次 webpack 編譯的 hash 值 cahe: true, // 默認值是 true。表示只有在內容變化時才生成一個新的文件 showErrors: true, // 如果 webpack 編譯出現錯誤,webpack會將錯誤資訊包裹在一個 pre 標籤內,屬性的默認值為 true /** chunks 選項的作用主要是針對多入口(entry)文件。當你有多個入口文件的時候,對應就會生成多個編譯後的 js 文件。那麼 chunks 選項就可以決定是否都使用這些生成的 js 文件。 chunks 默認會在生成的 html 文件中引用所有的 js 文件,當然你也可以指定引入哪些特定的文件。 **/ // chunks: ['index','index2'], }) ]
css樣式
yarn add css-loader style-loader less less-loader -D
在index.js中引入css|less模組
// src/index.js let name = require('./a.js'); require('./assets/css/index.css'); require('./assets/css/commom.less'); console.log('hello webpack4.0'); console.log(name);
module: { // 模組 rules: [ // loader的順序 默認是從右往左,從上到下 // css-loader 解析 @import 這種語法的 // style-loader 將css引入html的head中 style標籤 // {test: /.css$/, use: ['style-loader','css-loader']} {test: /.(css|less)$/, use: [ { loader: 'style-loader', options: { insertAt: 'top' // 插入頂部 這樣就會被後面的樣式覆蓋 } }, 'css-loader', 'less-loader' ] } ] },
mini-css-extract-plugin
yarn add mini-css-extract-plugin -D
上面打包css會把css文件以style標籤的形式寫入index.html
,現在我們就來把它們單獨打包成文件。
module: { // 模組 rules: [ {test: /.(css|less)$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'less-loader' ] } ] }, plugins: [ new MiniCssExtractPlugin({ filename: 'assets/css/index.css' // 打包到dist/assets/css/index.css }) ]
css3 自動添加各種瀏覽器前綴:
yarn add postcss-loader autoprefixer -D
// postcss.config.js module.exports = { plugins: [require('autoprefixer')({'browsers': ['> 1%', 'last 2 versions']})] } // webpack.config.js module: { // 模組 rules: [ {test: /.(css|less)$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader' ] } ] },
推薦用法是在package.json
中設置:
Replace Autoprefixer browsers option to Browserslist config. Use browserslist key in package.json or .browserslistrc file.
// postcss.config.js module.exports = { plugins: [require('autoprefixer')] }
"browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ]
壓縮css:
⚠️壓縮css也要壓縮js,不如js不會壓縮。
yarn add optimize-css-assets-webpack-plugin terser-webpack-plugin -D
// webpack.config.js mode:'production', // * development不會壓縮 optimization: { minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})], },
處理js
yarn add babel-loader @babel/babel-core @babel/preset-env -D
⚠️
@babel/babel-core
和@babel/preset-env
與babel-core
和babel-preset-env
不一樣
// webpack.config.js module: { rules: [ { test: /.js$/, exclude: '/node_modules', include: 'src', use: { loader: 'babel-loader', options: { // 配置預設 presets: [ '@babel/preset-env' ] } } } ] }
或者:
// .babelrc { "presets": ["@babel/preset-env"] }
處理高級版本js
babel-runtime 是供編譯模組復用工具函數,是錦上添花。 babel-polyfil是雪中送炭,是轉譯沒有的api。
// 示例 class Person{ constructor(name, age) { this.name = name; this.age = age; } } let person = new Person('FinGet',24); console.log(person.name); // 高級api console.log('FinGet'.includes('Get'));
yarn add @babel/plugin-transform-runtime -D // @babel/runtime as a production dependency (since it's for the "runtime"). yarn add @babel/runtime
使用:
// .babelrc "plugins": ["@babel/plugin-transform-runtime"]
@babel/runtime
會在打包的js中,注入一些腳本,所以要安裝production依賴
yarn add @babel/polyfill
使用:
require("@babel/polyfill"); // or import "@babel/polyfill"; // or // webpack.config.js module.exports = { entry: ["@babel/polyfill", "./app/js"], };
這樣引入會導致打包出來的js很大

按需引入:
// .babelrd { "presets": [["@babel/preset-env", { "useBuiltIns": "usage" }]], }
關鍵點是useBuiltIns
這一配置項,它的值有三種:
false
: 不對polyfills
做任何操作entry
: 根據target
中瀏覽器版本的支援,將polyfills
拆分引入,僅引入有瀏覽器不支援的polyfill
usage
(新):檢測程式碼中ES6/7/8等的使用情況,僅僅載入程式碼中用到的polyfills

ESlint 檢測語法
yarn add eslint eslint-loader -D
在根目錄下生成一個.eslint.json
來配置規則。
{ "parserOptions": { "ecmaVersion": 5, "sourceType": "script", "ecmaFeatures": {} }, "rules": { // 允許console "no-console": "off", // 允許空語句塊 "no-empty": ["error", { "allowEmptyCatch": true }], // 強制關鍵字周圍空格的一致性 (keyword-spacing) "keyword-spacing": "error", // 把 var 語句看作是在塊級作用域範圍之內 "block-scoped-var": "error", // 要求遵循大括弧約定 "curly": "error", // switch 要有default分支 "default-case": "error", // no-eq-null 禁止與null進行比較 "no-eq-null": "error", // 禁止使用多個空格 "no-multi-spaces": ["error", {"exceptions": { "Property": true }}], // 禁止多行字元串 "no-multi-str": "error", // 禁止使用 new 以避免產生副作用 "no-new": "error", // 數組中的空格 "array-bracket-spacing": ["error", "never"], // 禁止或強制在程式碼塊中開括弧前和閉括弧後有空格 "block-spacing": "error", // 大括弧風格要求 "brace-style": ["error", "1tbs", { "allowSingleLine": true }], // 逗號前後使用一致的空格 "comma-spacing": ["error", { "before": false, "after": true }], // 逗號風格 "comma-style": ["error", "last"], // 計算屬性不使用空格 "computed-property-spacing": ["error", "never"], // 函數標識符和其調用之間禁止空格 "func-call-spacing": ["error", "never"], // 箭頭函數函數體的位置 "implicit-arrow-linebreak": ["error", "beside"], // tab縮進 "indent": ["error", "tab", { "SwitchCase": 1 }], // 對象key-value空格 "key-spacing": ["error", { "beforeColon": false }], // 行注釋位置 "line-comment-position": ["error", { "position": "above" }], // 類成員之間需要空行 "lines-between-class-members": ["error", "always"], // 要求構造函數首字母大寫 "new-cap": "error", // 調用無參構造函數時帶括弧 "new-parens": "error", // 禁止使用 Array 構造函數 "no-array-constructor": "error", // 禁止使用內聯注釋 "no-inline-comments": "error", // 禁止連續賦值 "no-multi-assign": "error", // 不允許多個空行 "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1 }], // 禁止使用 Object 構造函數 "no-new-object": "error", // 禁用行尾空白 "no-trailing-spaces": "error", // 禁止屬性前有空白 "no-whitespace-before-property": "error", // 強制在花括弧內使用一致的換行符 "object-curly-newline": ["error", { "ImportDeclaration": "always", "ExportDeclaration": "always" }], // 花括弧中使用一致的空格 "object-curly-spacing": ["error", "never"], // 要求在變數聲明周圍換行 "one-var-declaration-per-line": ["error", "always"], // 禁止塊內填充 "padded-blocks": ["error", "never"], // 語句間填充空行 "padding-line-between-statements": [ "error", { "blankLine": "always", "prev": ["const", "let", "var"], "next": "*"}, { "blankLine": "any", "prev": ["const", "let", "var"], "next": ["const", "let", "var"]}, { "blankLine": "always", "prev": "directive", "next": "*" }, { "blankLine": "any", "prev": "directive", "next": "directive" } ], // 強制使用一致的反勾號、雙引號或單引號 "quotes": ["error", "single", { "allowTemplateLiterals": true }], // 對象字面量屬性名稱使用引號 "quote-props": ["error", "as-needed"], // 行尾分號 "semi": ["error", "always"], // 分號前後空格 "semi-spacing": ["error", {"before": false, "after": true}], // 分號位置 "semi-style": ["error", "last"], // 語句塊之前的空格 "space-before-blocks": "error", // function空格 "space-before-function-paren": ["error", { "anonymous": "always", "named": "never", "asyncArrow": "always" }], // 禁止圓括弧內的空格 "space-in-parens": "error", // 要求中綴操作符周圍有空格 "space-infix-ops": "error", // 要求或禁止在一元操作符之前或之後存在空格 "space-unary-ops": ["error", {"words": true, "nonwords": false}], // 要求或禁止在注釋前有空白 "spaced-comment": ["error", "always"], // 強制在 switch 的冒號左右有空格 "switch-colon-spacing": "error", // 要求正則表達式被包裹起來 "wrap-regex": "error", // ES6 // 要求箭頭函數體使用大括弧 "arrow-body-style": "error", // 要求箭頭函數的箭頭之前或之後有空格 "arrow-spacing": "error", // 禁止重複導入 }, "env": {} }
{ test: /.js$/, loader: ['babel-loader', 'eslint-loader'], } // or { test: /.js$/, use: { loader: 'eslint-loader', options: { enforce: 'pre' // 先執行 } } }
打包圖片
- js中創建圖片引入
import jpg from './assets/snail.jpg' let img = new Image(); img.src = jpg document.body.appendChild(img);
- css背景圖引入
body{ background-image: url(../logo.svg); }
- html img標籤引入
<img src="../src/assets/snail.jpg" alt="">
file-loader
yarn add file-loader -D
file-loader
會默認在內部生成生成一張圖片,到dist目錄下,把生成圖片的名字返回回來
{ test: /.(png|jpe?g|gif|svg)(?.*)?$/, use: 'file-loader' }
html-withimg-loader
html中直接使用img標籤src載入圖片的話,因為沒有被依賴,圖片將不會被打包。
yarn add html-withimg-loader
使用:
{ test: /.(htm|html)$/i, loader: 'html-withimg-loader' }
url-loader
如果圖片較多,會發很多http請求,會降低頁面性能。這個問題可以通過url-loader解決。url-loader會將引入的圖片編碼,生成dataURl。相當於把圖片數據翻譯成一串字元。再把這串字元打包到文件中,最終只需要引入這個文件就能訪問圖片了。當然,如果圖片較大,編碼會消耗性能。因此url-loader提供了一個limit參數,小於limit位元組的文件會被轉為DataURl,大於limit的還會使用file-loader進行copy。
url-loader和file-loader是什麼關係呢?簡答地說,url-loader封裝了file-loader。url-loader不依賴於file-loader,即使用url-loader時,只需要安裝url-loader即可,不需要安裝file-loader,因為url-loader內置了file-loader。
yarn add url-loader -D
{ test: /.(png|jpe?g|gif|svg)(?.*)?$/, use: { loader: 'url-loader', options: { name: '[name].[ext]', // 保持名稱不變 limit: 20*1024, // 小於20k的圖片 打包成base64 outputPath: 'assets/' // 打包後的存放路徑 dist/assets } } },
output.publicPath
此選項指定在瀏覽器中所引用的「此輸出目錄對應的公開 URL」。相對 URL(relative URL) 會被相對於 HTML 頁面(或 標籤)解析。相對於服務的 URL(Server-relative URL),相對於協議的 URL(protocol-relative URL) 或絕對 URL(absolute URL) 也可是可能用到的,或者有時必須用到,例如:當將資源託管到 CDN 時。
module.exports = { //... output: { path: path.resolve(__dirname, 'dist'), publicPath: 'https://cdn.example.com/assets/' } };
⚠️也可以單獨給圖片的options下配一個publicPath
source-map
生產模式會壓縮程式碼成一行,就沒法調試了。
... ️mode:'developmen', //production 不會生成map文件 entry: './src/index.js', devtool: "source-map", // 增加映射文件 ...

webpack 高級配置
watch
... entry: entry: './src/index.js', // build 監控,變化自動打包 watch: true, watchOptions: { // 監控選項 poll: 1000, // 每秒 watch 1000次 aggregateTimeout: 500, // 防抖 ignored: '/node_modules/' //不需要監控的文件 }, ...
clean-webpack-plugin
每次打包之前,都刪除dist目錄下的文件。
yarn add clean-webpack-plugin -D
clean-webpack-plugin: ^3.00
const {CleanWebpackPlugin} = require('clean-webpack-plugin'); plugins: [ new CleanWebpackPlugin() ]
export { CleanWebpackPlugin };//3.0.0導出方式 export default CleanWebpackPlugin;//2.0.2導出方式 所以在2.0.2版本我們可以直接require拿到CleanWebpackPlugin const CleanWebpackPlugin = require('clean-webpack-plugin') module.exports = CleanWebpackPlugin;//1.0.1導出方式
他會默認清空我們output裡面設置的所有文件夾
https://github.com/johnagan/clean-webpack-plugin#options-and-defaults-optional By default, this plugin will remove all files inside webpack's output.path directory, as well as all unused webpack assets after every successful rebuild.
copy-webpack-plugin
拷貝文件
yarn add copy-webpack-plugin -D
const CopyPlugin = require('copy-webpack-plugin'); plugins: [ new CopyPlugin([ { from: 'src/assets', to: 'assets' } ]), ]
BannerPlugin
版權聲明
plugins:[ new webpack.BannerPlugin('CopyRight by FinGet!') ] // 會在打包文件頭部加上 /*! CopyRight by FinGet! */
// 配置選項 { banner: string | function, // 其值為字元串或函數,將作為注釋存在 raw: boolean, // 如果值為 true,將直出,不會被作為注釋 entryOnly: boolean, // 如果值為 true,將只在入口 chunks 文件中添加 test: string | RegExp | Array, include: string | RegExp | Array, exclude: string | RegExp | Array, }
resolve
module.exports = { resolve: { // 解析第三方包 alias: { // 創建 import 或 require 的別名,來確保模組引入變得更簡單。 '@': path.resolve(__dirname, 'src') }, extensions: ['.js','.css','.json'], // 自動解析確定的擴展 就是沒有後綴名時,按這個順序匹配 modules: [path.resolve('node_modules')] //告訴 webpack 解析模組時應該搜索的目錄 }, }
點這裡查看更多配置項。
DefinePlugin
定義一些全局變數。
module.exports = { plugins: [ new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true), VERSION: JSON.stringify('5fa3b9'), BROWSER_SUPPORTS_HTML5: true, TWO: '1+1', 'typeof window': JSON.stringify('object'), 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) }); ] }
注意,因為這個插件直接執行文本替換,給定的值必須包含字元串本身內的實際引號。通常,有兩種方式來達到這個效果,使用 『「production」『, 或者使用 JSON.stringify(『production』)。
webpack-merge
分別配置不同的環境打包文件。
yarn add webpack-merge -D
// build/webpack.base.conf.js const webpack = require('webpack'); const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { entry: path.resolve(__dirname,'../src/index.js'), // 打包入口文件 output: { filename: 'bundle.[hash:8].js', // 打包後的文件名 path: path.resolve(__dirname, '../dist') // 這個路徑必須是一個絕對路徑,所以需要用path來解析一下 }, module: { // 模組 rules: [ { test: /.(css|less)$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader' ] }, { test: /.js$/, loader: 'babel-loader', }, { test: /.(png|jpe?g|gif|svg)(?.*)?$/, use: { loader: 'url-loader', options: { limit: 1, outputPath: 'assets/images' // 打包後的存放路徑 } } }, { test: /.(htm|html)$/i, loader: 'html-withimg-loader' } ] }, // 配置插件 plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ template: path.resolve(__dirname, '../public/index.html'), // 模版路徑 filename: 'index.html', // 打包後的文件名 title: 'webpack4.0', // 顧名思義,設置生成的 html 文件的標題 inject: true, hash: true, // hash選項的作用是 給生成的 js 文件一個獨特的 hash 值,該 hash 值是該次 webpack 編譯的 hash 值 cahe: true, // 默認值是 true。表示只有在內容變化時才生成一個新的文件 showErrors: true, // 如果 webpack 編譯出現錯誤,webpack會將錯誤資訊包裹在一個 pre 標籤內,屬性的默認值為 true }), new MiniCssExtractPlugin({ filename: 'assets/css/index.css' }) ] }
// build/webpack.pro.cong.js const merge = require('webpack-merge'); const base = require('./webpack.base.conf'); const TerserJSPlugin = require('terser-webpack-plugin'); const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); mmodule.exports = merge(base, { mode: 'production', optimization: { minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})], }, plugins: [ // 文件頭部注入 new webpack.BannerPlugin('CopyRight by FinGet!') ] })
// build/webpack.dev.cong.js const merge = require('webpack-merge'); const webpack = require('webpack'); const base = require('./webpack.base.conf'); mmodule.exports = merge(base, { mode: 'development', // 開發伺服器的配置 官方文檔: https://webpack.docschina.org/configuration/dev-server/ devServer: { contentBase: path.resolve(__dirname, "../dist"), // 告訴伺服器從哪個目錄中提供內容。只有在你想要提供靜態文件時才需要。 // publicPath: './dist', // 將用於確定應該從哪裡提供 bundle,並且此選項優先。 此路徑下的打包文件可在瀏覽器中訪問。 port: 3000, // 埠 progress: true, // 打包過程 open: true, // 自動打開瀏覽器 }, devtool: 'source-map', plugins: [ new webpack.DefinePlugin({ 'process.env': { 'NODE_ENV': JSON.stringify(process.env.NODE_ENV) } }) ], })
yarn run dev -- --config build/webpack.dev.conf.js yarn run build -- --config build/webpack.pro.conf.js
webpack 優化
noParse
防止 webpack 解析那些任何與給定正則表達式相匹配的文件。
module.exports = { //... module: { noParse: /jquery|lodash/, } };
happyPack 多執行緒打包
js、css、img都可以多執行緒打包,提高打包速度。
yarn add happypack -D
module.exports = { module:{ { test: /.js$/, use: 'Happypack/loader?id=js' } } plugins:[ new Happypack({ id: 'js', // id與上面對應 use: [{ loader: 'babel-loader', options: { presets:['@babel/preset-env'] } }] }) ] }
tree-shaking
(webpack 自帶)把沒用的程式碼刪除掉。
import
在生產環境下 會自動去掉沒用的程式碼。es6 模組會把結果放到default
上。
// test.js let sum = (a,b) => { return a+b; } let minus = (a,b) => { return a-b; } export default {sum,minus}
import calc from './test.js'; console.log(calc.add(1,2)); let calc = require('./test'); console.log(calc.default.sum(1,2));
這裡沒用minus
方法,在import
方式打包中會tree-shaking
,require
則不會。
scope hosting
let a = 1; let b = 2; let c = 3; let d = a + b + c; console.log(d);
這個程式碼很啰嗦,在打包之後,webpack會自動分析,省略程式碼。
// 打包後 console.log(6);
抽離公共程式碼
多入口項目,多個入口,引用同一個js/css,則可以抽離公共程式碼。
module.exports = { optimization: { splitChunks: { // 分割程式碼塊 cacheGroups: { // 快取組 common: { // 公共模組 chunks: 'initial', minSize: 0, minChunks: 2, } } } }, }
// 把第三方模組單獨打包 比如jquery、lodash module.exports = { optimization: { splitChunks: { // 分割程式碼塊 cacheGroups: { // 快取組 common: { // 公共模組 chunks: 'initial', minSize: 0, minChunks: 2, }, // 單獨打包第三方模組 vendor: { priority: 1, // 優先順序別 test: /[\/]node_modules[\/]/, chunks: 'initial', name(module, chunks, cacheGroupKey) { const moduleFileName = module.identifier().split('/').reduceRight(item => item); return `${moduleFileName}`; }, minSize: 0, minChunks: 2 } } } }, }
optimization參數介紹:
optimization: { splitChunks: { chunks: "initial", // 程式碼塊類型 必須三選一: "initial"(初始化) | "all"(默認就是all) | "async"(動態載入) minSize: 0, // 最小尺寸,默認0 minChunks: 1, // 最小 chunk ,默認1 maxAsyncRequests: 1, // 最大非同步請求數, 默認1 maxInitialRequests: 1, // 最大初始化請求書,默認1 name: () => {}, // 名稱,此選項課接收 function cacheGroups: { // 快取組會繼承splitChunks的配置,但是test、priorty和reuseExistingChunk只能用於配置快取組。 priority: "0", // 快取組優先順序 false | object | vendor: { // key 為entry中定義的 入口名稱 chunks: "initial", // 必須三選一: "initial"(初始化) | "all" | "async"(默認就是非同步) test: /react|lodash/, // 正則規則驗證,如果符合就提取 chunk name: "vendor", // 要快取的 分隔出來的 chunk 名稱 minSize: 0, minChunks: 1, enforce: true, reuseExistingChunk: true // 可設置是否重用已用chunk 不再創建新的chunk } } } }
點擊這裡查看更多配置。
懶載入
在用戶觸發一個點擊操作才載入需要的文件。
// lazy.js export default '懶載入';
// test.js function handleClick() { import('./lazy.js').then(module => { console.log(module.default); }) }