module:{ rules:[ { test:/\.js$/, use:['babel-loader?cacheDirectory'], include:path.resolve(__dirname,'src'), exclude:/node_modules/ } ] }
resolve: { modules: [path.resolve(__dirname, 'node_modules')] },
mainFields
用於配置第三方模塊使用那個入口文件 isomorphic-fetch
resolve.alias
配置項經過別名來把原導入路徑映射成一個新的導入路徑 此優化方法會影響使用Tree-Shaking
去除無效代碼
alias: { 'react': path.resolve(__dirname, './node_modules/react/cjs/eact.production.min.js') }
extensions: ['.js', '.json']
resolve: { extensions: ['js'] },
module: { noParse: [/react\.min\.js/] }
被忽略掉的文件裏不該該包含 import 、 require 、 define 等模塊化語句css
module.exports = { entry: { react: ['react'] //react模塊打包到一個動態鏈接庫 }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].dll.js', //輸出動態鏈接庫的文件名稱 library: '_dll_[name]' //全局變量名稱 }, plugins: [ new webpack.DllPlugin({ name: '_dll_[name]', //和output.library中一致,值就是輸出的manifest.json中的 name值 path: path.join(__dirname, 'dist', '[name].manifest.json') }) ] }
webpack --config webpack.dll.config.js --mode production
plugins: [ new webpack.DllReferencePlugin({ manifest: require(path.join(__dirname, 'dist', 'react.manifest.json')), }) ],
webpack --config webpack.config.js --mode development
npm i happypack@next -D
module: { rules: [{ test: /\.js$/, //把對.js文件的處理轉交給id爲babel的HappyPack實例 use: 'happypack/loader?id=babel', include: path.resolve(__dirname, 'src'), exclude: /node_modules/ }, { //把對.css文件的處理轉交給id爲css的HappyPack實例 test: /\.css$/, use: 'happypack/loader?id=css', include: path.resolve(__dirname, 'src') }], noParse: [/react\.min\.js/] },
plugins: [ //用惟一的標識符id來表明當前的HappyPack是用來處理一類特定文件 new HappyPack({ id: 'babel', //如何處理.js文件,和rules裏的配置相同 loaders: [{ loader: 'babel-loader', query: { presets: [ "env", "react" ] } }] }), new HappyPack({ id: 'css', loaders: ['style-loader', 'css-loader'], threads: 4, //表明開啓幾個子進程去處理這一類型的文件 verbose: true //是否容許輸出日子 }) ],
ParallelUglifyPlugin
能夠把對JS文件的串行壓縮變爲開啓多個子進程並行執行
npm i -D webpack-parallel-uglify-plugin
new ParallelUglifyPlugin({ workerCount: 3, //開啓幾個子進程去併發的執行壓縮。默認是當前運行電腦的 CPU 核數減去1 uglifyJS: { output: { beautify: false, //不須要格式化 comments: false, //不保留註釋 }, compress: { warnings: false, // 在UglifyJs刪除沒有用到的代碼時不輸出警告 drop_console: true, // 刪除全部的 `console` 語句,能夠兼容ie瀏覽器 collapse_vars: true, // 內嵌定義了可是隻用到一次的變量 reduce_vars: true, // 提取出出現屢次可是沒有定義成變量去引用的靜態值 } }, })
watch: true, //只有在開啓監聽模式時,watchOptions纔有意義 watchOptions: { ignored: /node_modules/, aggregateTimeout: 300, //監聽到變化發生後等300ms再去執行動做,防止文件更新太快致使編譯頻率過高 poll: 1000 //經過不停的詢問文件是否改變來判斷文件是否發生變化,默認每秒詢問1000次 }
aggregateTimeout
配置devServer: { contentBase: './dist', inline: true },
webpack負責監聽文件變化,webpack-dev-server負責刷新瀏覽器 這些文件會被打包到chunk中,它們會代理客戶端向服務器發起WebSocket鏈接node
(webpack)-dev-server/client/overlay.js 3.58 KiB {0} [built] (webpack)-dev-server/client/socket.js 1.05 KiB {0} [built] ./node_modules/loglevel/lib/loglevel.js 7.68 KiB {0} [built] ./node_modules/strip-ansi/index.js 161 bytes {0} [built] ./node_modules/url/url.js 22.8 KiB {0} [built] (webpack)-dev-server/client?http://localhost:8080 7.75 KiB {0} [built] multi (webpack)-dev-server/client?http://localhost:8080 ./src/index.js 40 bytes {0} [built]
devServer: { hot:true }
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
[0] multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/index.js 52 bytes {main} [built]
[./node_modules/webpack/hot/dev-server.js] (webpack)/hot/dev-server.js 1.66 KiB {main} [built]
[./node_modules/webpack/hot/emitter.js] (webpack)/hot/emitter.js 77 bytes {main} [built]
if (module.hot) { module.hot.accept('./index.js', function () { console.log('accept index.js'); }); }
優化模塊熱替換瀏覽器日誌react
plugins: [ new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin(), ]
在開發網頁的時候,通常都會有多套運行環境,例如:webpack
if(process.env.NODE_ENV == 'production'){ console.log('生產環境'); }else{ console.log('開發環境'); }
當你使用process模塊的時候,webpack會把process模塊打包進來git
new webpack.DefinePlugin({ 'process.env': { NODE_ENV:JSON.stringify('production') } }),
定義環境變量的值時用 JSON.stringify 包裹字符串的緣由是環境變量的值須要是一個由雙引號包裹的字符串,而 JSON.stringify('production')的值正好等於'"production"'github
new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), })
output: { path: path.resolve(__dirname, 'dist'), filename: '[name]_[hash:8].js', publicPath: 'http://img.zhufengpeixun.cn' },
Tree Shaking
能夠用來剔除JavaScript
中用不上的死代碼。它依賴靜態的ES6
模塊化語法,例如經過import
和export
導入導出。{ loader: 'babel-loader', query: { presets: [ [ "env", { modules: false //含義是關閉 Babel 的模塊轉換功能,保留本來的 ES6 模塊化語法 } ], "react" ] } }
webpack --display-used-exports
const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); plugins: [ new UglifyJSPlugin() ]
webpack --display-used-exports --optimize-minimize
webpack --mode production
entry: { pageA: './src/pageA', pageB: './src/pageB' }, optimization: { splitChunks: { cacheGroups: { commons: { chunks: "initial", minChunks: 2, maxInitialRequests: 5, // The default limit is too small to showcase the effect minSize: 0 // This is example is too small to create commons chunks }, vendor: { test: /node_modules/, chunks: "initial", name: "vendor", priority: 10, enforce: true } } } },
export default 'Hello';
import str from './hello.js';
console.log(str);
var util = ('Hello'); console.log(util);
函數由兩個變成了一個,hello.js 中定義的內容被直接注入到了 main.js 中web
const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin'); module.exports = { resolve: { // 針對 Npm 中的第三方模塊優先採用 jsnext:main 中指向的 ES6 模塊化語法的文件 mainFields: ['jsnext:main', 'browser', 'main'] }, plugins: [ // 開啓 Scope Hoisting new ModuleConcatenationPlugin(), ], };
--display-optimization-bailout
entry: { index: './src/index.js', another: './src/another-module.js' }
optimization: { splitChunks: { cacheGroups: { commons: { chunks: "initial", minChunks: 2 }, vendor: { test: /node_modules/, chunks: "initial", name: "vendor", } }
document .getElementById('clickMe') .addEventListener('click', () => { import (/*webpackChunkName:"alert"*/ './alert').then(alert => { console.log(alert); alert.default('hello'); }); });
loaders: [ { loader: 'babel-loader', query: { presets: ["env", "stage-0", "react"] } } ]
const path = require("path") const express = require("express") const webpack = require("webpack") const webpackDevMiddleware = require("webpack-dev-middleware") const webpackConfig = require('./webpack.config.js') const app = express(), DIST_DIR = path.join(__dirname, "dist"),// 設置靜態訪問文件路徑 PORT = 9090, // 設置啓動端口 complier = webpack(webpackConfig) app.use(webpackDevMiddleware(complier, { //綁定中間件的公共路徑,與webpack配置的路徑相同 publicPath: webpackConfig.output.publicPath, quiet: true //向控制檯顯示內容 })) // 這個方法和下邊註釋的方法做用同樣,就是設置訪問靜態文件的路徑 app.use(express.static(DIST_DIR)) app.listen(PORT,function(){ console.log("成功啓動:localhost:"+ PORT) })
webpack --profile --json > stats.json
Webpack 官方提供了一個可視化分析工具 Webpack Analyseexpress
當用 Webpack 去構建一個能夠被其餘模塊導入使用的庫時須要用到它們。 npm
output.libraryTarget 是字符串的枚舉類型,支持如下配置。 json
編寫的庫將經過 var 被賦值給經過 library 指定名稱的變量。
假如配置了 output.library='LibraryName',則輸出和使用的代碼以下:
// Webpack 輸出的代碼 var LibraryName = lib_code; // 使用庫的方法 LibraryName.doSomething(); 假如 output.library 爲空,則將直接輸出:
lib_code 其中 lib_code 代指導出庫的代碼內容,是有返回值的一個自執行函數。
編寫的庫將經過 CommonJS 規範導出。
假如配置了 output.library='LibraryName',則輸出和使用的代碼以下:
// Webpack 輸出的代碼 exports['LibraryName'] = lib_code; // 使用庫的方法 require('library-name-in-npm')['LibraryName'].doSomething(); 其中 library-name-in-npm 是指模塊發佈到 Npm 代碼倉庫時的名稱。
編寫的庫將經過 CommonJS2 規範導出,輸出和使用的代碼以下:
// Webpack 輸出的代碼 module.exports = lib_code; // 使用庫的方法 require('library-name-in-npm').doSomething(); CommonJS2 和 CommonJS 規範很類似,差異在於 CommonJS 只能用 exports 導出,而 CommonJS2 在 CommonJS 的基礎上增長了 module.exports 的導出方式。 在 output.libraryTarget 爲 commonjs2 時,配置 output.library 將沒有意義。
編寫的庫將經過 this 被賦值給經過 library 指定的名稱,輸出和使用的代碼以下:
// Webpack 輸出的代碼 this['LibraryName'] = lib_code; // 使用庫的方法 this.LibraryName.doSomething();
編寫的庫將經過 window 被賦值給經過 library 指定的名稱,即把庫掛載到 window 上,輸出和使用的代碼以下:
// Webpack 輸出的代碼 window['LibraryName'] = lib_code; // 使用庫的方法 window.LibraryName.doSomething();
global
編寫的庫將經過 global 被賦值給經過 library 指定的名稱,即把庫掛載到 global 上,輸出和使用的代碼以下: // Webpack 輸出的代碼 global['LibraryName'] = lib_code; // 使用庫的方法 global.LibraryName.doSomething();