下面是webpack.conf.prod.js 部分內(nèi)容
const path = require("path");
const config = {
mode: "production",
resolve: webpackConfigResolve,
stats: "minimal",
entry: './app.js';
output: {
filename:'bundle.js',
},
module: {
rules: webpackConfigmModuleRules,
},
optimization: {},
plugins: [],
};
首先認(rèn)識下webpack每項配置項
entry
待更
output
待更
module
待更
resolve
webpack 在啟動后會從配置的入口模塊出發(fā)找出所有依賴的模塊户盯,resolve配置 webpack 如何尋找模塊所對應(yīng)的文件跨跨。 webpack 內(nèi)置 JavaScript 模塊化語法解析功能谋作,默認(rèn)會采用模塊化標(biāo)準(zhǔn)里約定好的規(guī)則去尋找,但你也可以根據(jù)自己的需要修改默認(rèn)的規(guī)則纽帖。如下配置
const path = require('path');
function resolve(dir) {
return path.join(__dirname, '..', dir);
}
module.exports = {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json', '.less', '.css'],
mainFields: ['module', 'jsnext:main', 'main'],
symlinks: false,
alias: {
'@': resolve('src'),
},
};
-
alias
resolve.alias
配置項通過別名來把原導(dǎo)入路徑映射成一個新的導(dǎo)入路徑隧土。例如使用以下配置:
resolve:{
alias:{
components: './src/components/'
}
}
當(dāng)你通過import Button from 'components/button
導(dǎo)入時嚣镜,實際上被 alias 等價替換成了 import Button from './src/components/button'
。
以上 alias 配置的含義是把導(dǎo)入語句里的components
關(guān)鍵字替換成./src/components/
剩瓶。
這樣做可能會命中太多的導(dǎo)入語句,alias 還支持 $ 符號來縮小范圍到只命中以關(guān)鍵字結(jié)尾的導(dǎo)入語句:
resolve:{
alias:{
'react$': '/path/to/react.min.js'
}
}
react$
只會命中以react
結(jié)尾的導(dǎo)入語句城丧,即只會把import 'react'
關(guān)鍵字替換成import '/path/to/react.min.js'
延曙。
-
mainFields
有一些第三方模塊會針對不同環(huán)境提供幾分代碼。 例如分別提供采用 ES5 和 ES6 的2份代碼亡哄,這2份代碼的位置寫在package.json
文件里枝缔,如下:
{
"jsnext:main": "es/index.js",// 采用 ES6 語法的代碼入口文件
"main": "lib/index.js" // 采用 ES5 語法的代碼入口文件
}
Webpack 會根據(jù) mainFields 的配置去決定優(yōu)先采用那份代碼, mainFields 默認(rèn)如下:
mainFields: ['browser', 'main']
Webpack 會按照數(shù)組里的順序去 package.json 文件里尋找磺平,只會使用找到的第一個
假如你想優(yōu)先采用 ES6 的那份代碼魂仍,可以這樣配置:
mainFields: ['jsnext:main', 'browser', 'main']
-
extensions
在導(dǎo)入語句沒帶文件后綴時,Webpack 會自動帶上后綴后去嘗試訪問文件是否存在拣挪。resolve.extensions
用于配置在嘗試過程中用到的后綴列表擦酌,默認(rèn)是:
extensions: ['.js', '.json']
也就是說當(dāng)遇到require('./data')
這樣的導(dǎo)入語句時,Webpack 會先去尋找./data.js
文件菠劝,如果該文件不存在就去尋找./data.json
文件赊舶, 如果還是找不到就報錯。
假如你想讓 Webpack 優(yōu)先使用目錄下的 TypeScript 文件赶诊,可以這樣配置:
extensions: ['.ts', '.js', '.json']
-
modules
resolve.modules 配置 Webpack 去哪些目錄下尋找第三方模塊笼平,默認(rèn)是只會去 node_modules 目錄下尋找。 有時你的項目里會有一些模塊會大量被其它模塊依賴和導(dǎo)入舔痪,由于其它模塊的位置分布不定寓调,針對不同的文件都要去計算被導(dǎo)入模塊文件的相對路徑, 這個路徑有時候會很長锄码,就像這樣import ../../../components/button'
這時你可以利用modules
配置項優(yōu)化夺英,假如那些被大量導(dǎo)入的模塊都在./src/components
目錄下晌涕,把 modules 配置成
modules:['./src/components','node_modules']
后,你可以簡單通過import 'button'
導(dǎo)入痛悯。
-
descriptionFiles
resolve.descriptionFiles
配置描述第三方模塊的文件名稱余黎,也就是 package.json 文件。默認(rèn)如下:
descriptionFiles: ['package.json']
enforceExtension
resolve.enforceExtension
如果配置為true
所有導(dǎo)入語句都必須要帶文件后綴载萌,例如開啟前import './foo'
能正常工作惧财,開啟后就必須寫成import './foo.js'
。enforceModuleExtension
enforceModuleExtension
和enforceExtension
作用類似扭仁,但enforceModuleExtension
只對node_modules
下的模塊生效垮衷。enforceModuleExtension
通常搭配enforceExtension
使用,在enforceExtension:true
時斋枢,因為安裝的第三方模塊中大多數(shù)導(dǎo)入語句沒帶文件后綴帘靡, 所以這時通過配置enforceModuleExtension:false
來兼容第三方模塊
plugins
常用的plugins如下
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const cssnano = require("cssnano");
const TerserPlugin = require("terser-webpack-plugin");
const HappyPack = require("happypack");
-
html-webpack-plugin
作用:生成html
const htmlPlugin = new HtmlWebpackPlugin({
filename: `${entry}.html`,
title: `${titles[entry]}`,
template: path.resolve(__dirname, '../../src/index.js'),
chunks: [
'vendors.core',
'vendors.commons',
],
minify: HtmlWebpackPluginMinifyOptions,
});
html-webpack-plugin插件詳細(xì)用法參見:
http://www.reibang.com/p/08a60756ffda
-
HotModuleReplacementPlugin
作用:頁面熱更新(模塊熱替換)
首先我們要確保項目是基于webpack-dev-server
或webpack-dev-middle
進(jìn)行開發(fā)的,webpack本身的命令行并不支持HMR瓤帚。webpack.conf.dev.js文件部分內(nèi)容如下:
const webpack = require('webpack');
module.exports = {
// ...
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer:{
hot:true,
}
}
也可以在頁面中開啟HMR描姚,比如下面這個例子:
import { add } from 'util.js';
add(2,3);
if(module.hot){
module.hot.accept();
}
熱更新原理:
css-loader、vue-loader已經(jīng)幫我們寫了這部分代碼戈次,所以不需要手寫了轩勘,但是如果是HTML,需要自己手動執(zhí)行下面的代碼
if (module.hot) {
module.hot.accept('文件地址', () => {
// 重新執(zhí)行文件
})
}
-
mini-css-extract-plugin(webpack 4及以上版本)
mini-css-extract-plugin可以理解成extract-text-webpack-plugin的升級版怯邪,它擁有更豐富的特性和更好的性能绊寻,從Webpack 4開始官方推薦使用該插件進(jìn)行樣式提取(Webpack 4以前的版本是用不了的)悬秉。
說到mini-css-extract-plugin的特性澄步,最重要的就是它支持按需加載CSS,以前在使用extract-text-webpack-plugin的時候我們是做不到這一點的和泌。舉個例子村缸,a.js通過import()函數(shù)異步加載了b.js,b.js里面加載了style.css武氓,那么style.css最終只能被同步加載(通過HTML的link標(biāo)簽)梯皿。但是現(xiàn)在mini-css-extract-plugin會單獨打包出一個0.css(假設(shè)使用默認(rèn)配置),這個CSS文件將由a.js通過動態(tài)插入link標(biāo)簽的方式加載县恕。
在webpack.conf.prod.js中引入:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './app.js',
output: {
filename:'[name].js',
},
mode: 'development',
module: {
rules: [{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath:'../',
},
},
'css-loader'
],
}],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename:'[name].css',
})
]
}
-
extract-text-webpack-plugin(webpack 4之前版本)
作用:提取樣式到css文件
在webpack.conf.prod.js中引入:
const ExtractTextplugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './app.js';
output: {
filename:'bundle.js',
},
mode:'development',
module: {
rules:[
{
test:/\.css$/,
use:ExtractTextplugin.extract({
fallback:'style-loader',
use:'css-loader',
})
}
]
},
plugins:[
new ExtractTextPlugin('bundle.css')
]
}
-
optimize-css-assets-webpack-plugin
作用:壓縮css
壓縮CSS文件的前提是使用extract-text-webpack-plugin或mini-css-extract-plugin將樣式提取出來东羹,接著使用optimize-css-assets-webpack-plugin來進(jìn)行壓縮,這個插件本質(zhì)上使用的是壓縮器cssnano忠烛,當(dāng)然我們也可以通過其配置進(jìn)行切換属提。具體請看下面的例子:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
// ...
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader',
}),
}
],
},
plugins: [new ExtractTextPlugin('style.css')],
optimization: {
minimizer: [new OptimizeCSSAssetsPlugin({
// 生效范圍,只壓縮匹配到的資源
assetNameRegExp: /\.optimize\.css$/g,
// 壓縮處理器美尸,默認(rèn)為 cssnano
cssProcessor: require('cssnano'),
// 壓縮處理器的配置
cssProcessorOptions: { discardComments: { removeAll: true } },
// 是否展示 log
canPrint: true,
})],
},
};
-
terser-webpack-plugin (webpack 4 集成)
作用:壓縮Javascript
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
//...
optimization: {
// 覆蓋默認(rèn)的 minimizer
minimizer: [
new TerserPlugin({
/* your config */
test: /\.js(\?.*)?$/i,
exclude: /\/excludes/,
})
],
},
};
-
webpack-bundle-analyzer
作用:分析打包后輸出的bundle體積大小垒拢。
配置如下:
const Analyzer = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
...
plugins: [
new Analyzer()
],
}
-
clean-webpack-plugin
作用:在每次構(gòu)建前清理 /dist 文件夾旬迹。
配置如下:
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
...
plugins:[
new CleanWebpackPlugin()
],
}
NamedModulesPlugin
詳見博客:
http://www.reibang.com/p/8499842defbeProvidePlugin
詳見博客:
http://www.reibang.com/p/be9dee84f9cfDefinePlugin
官方鏈接:
https://webpack.docschina.org/plugins/define-plugin/
采坑注意:
https://segmentfault.com/a/1190000017217915SourceMapDevToolPlugin
待續(xù)
https://webpack.docschina.org/plugins/source-map-dev-tool-plugin/
參考博客:
https://www.cnblogs.com/joyco773/p/9049760.html
http://www.reibang.com/p/755aad97d810
http://www.reibang.com/p/2df87e8f4d3e
http://www.reibang.com/p/d08d5bc85ad2