webpack做爲一個模塊打包器,主要用於前端工程中的依賴梳理和模塊打包,將咱們開發的具備高可讀性和可維護性的代碼文件打包成瀏覽器能夠識別並正常運行的壓縮代碼,主要包括樣式文件處理成
css
,各類新式的JavaScript
轉換成瀏覽器認識的寫法等,也是前端工程師進階的不二法門。javascript
Webpack
裏一切皆模塊,Webpack
會從配置的Entry
開始遞歸找出全部依賴的模塊,最經常使用的是rules
配置項,功能是匹配對應的後綴,從而針對代碼文件完成格式轉換和壓縮合並等指定的操做。Module
模塊中的rules
中的配置項來使用。Webpack
構建流程中的特定時機注入擴展邏輯來改變構建結果或作你想要的事情。(插件API
)Webpack
通過一系列處理並得出最終想要的代碼後輸出結果,配置項用於指定輸出文件夾,默認是./dist
。webpack-dev-server
這個插件的配置項。development
| production
)來加載對應的默認配置entry
裏配置的module
開始遞歸解析entry
所依賴的全部module
module
都會根據rules
的配置項去尋找用到的loader
,接受所配置的loader
的處理entry
中的配置對象爲分組,每個配置入口和其對應的依賴文件最後組成一個代碼塊文件(chunk)並輸出webpack
會在恰當的時機執行plugin
的邏輯,來完成自定義的插件邏輯首先經過如下的腳本命令來創建初始化文件:css
npm init -y
npm i webpack webpack-cli -D // 針對webpack4的安裝
mkdir src && cd src && touch index.html index.js
cd ../ && mkdir dist && mkdir static
touch webpack.config.js
npm i webpack-dev-server --save-dev
複製代碼
修改生成的package.json
文件,來引入webpack
打包命令:html
"scripts": {
"build": "webpack --mode production",
"dev": "webpack-dev-server --open --mode development"
}
複製代碼
對webpack.config.js
文件加入一些基本配置loader
,從而基本的webpack4.x
的配置成型(以兩個頁面入口爲例):前端
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin') // 複製靜態資源的插件
const CleanWebpackPlugin = require('clean-webpack-plugin') // 清空打包目錄的插件
const HtmlWebpackPlugin = require('html-webpack-plugin') // 生成html的插件
const ExtractTextWebapckPlugin = require('extract-text-webpack-plugin') //CSS文件單獨提取出來
const webpack = require('webpack')
module.exports = {
entry: {
index: path.resolve(__dirname, 'src', 'index.js'),
page: path.resolve(__dirname, 'src', 'page.js'),
vendor:'lodash' // 多個頁面所需的公共庫文件,防止重複打包帶入
},
output:{
publicPath: '/', //這裏要放的是靜態資源CDN的地址
path: path.resolve(__dirname,'dist'),
filename:'[name].[hash].js'
},
resolve:{
extensions: [".js",".css",".json"],
alias: {} //配置別名能夠加快webpack查找模塊的速度
},
module: {
// 多個loader是有順序要求的,從右往左寫,由於轉換的時候是從右往左轉換的
rules:[
{
test: /\.css$/,
use: ExtractTextWebapckPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader'] // 再也不須要style-loader放到html文件內
}),
include: path.join(__dirname, 'src'), //限制範圍,提升打包速度
exclude: /node_modules/
},
{
test:/\.less$/,
use: ExtractTextWebapckPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader', 'less-loader']
}),
include: path.join(__dirname, 'src'),
exclude: /node_modules/
},
{
test:/\.scss$/,
use: ExtractTextWebapckPlugin.extract({
fallback: 'style-loader',
use:['css-loader', 'postcss-loader', 'sass-loader']
}),
include: path.join(__dirname, 'src'),
exclude: /node_modules/
},
{
test: /\.jsx?$/,
use: {
loader: 'babel-loader',
query: { //同時能夠把babel配置寫到根目錄下的.babelrc中
presets: ['env', 'stage-0'] // env轉換es6 stage-0轉es7
}
}
},
{ //file-loader 解決css等文件中引入圖片路徑的問題
// url-loader 當圖片較小的時候會把圖片BASE64編碼,大於limit參數的時候仍是使用file-loader 進行拷貝
test: /\.(png|jpg|jpeg|gif|svg)/,
use: {
loader: 'url-loader',
options: {
outputPath: 'images/', // 圖片輸出的路徑
limit: 1 * 1024
}
}
}
]
},
plugins: [
// 多入口的html文件用chunks這個參數來區分
new HtmlWebpackPlugin({
template: path.resolve(__dirname,'src','index.html'),
filename:'index.html',
chunks:['index', 'vendor'],
hash:true,//防止緩存
minify:{
removeAttributeQuotes:true//壓縮 去掉引號
}
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname,'src','page.html'),
filename:'page.html',
chunks:['page', 'vendor'],
hash:true,//防止緩存
minify:{
removeAttributeQuotes:true//壓縮 去掉引號
}
}),
new webpack.ProvidePlugin({
_:'lodash' //全部頁面都會引入 _ 這個變量,不用再import引入
}),
new ExtractTextWebapckPlugin('css/[name].[hash].css'), // 其實這個特性只用於打包生產環境,測試環境這樣設置會影響HMR
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, 'static'),
to: path.resolve(__dirname, 'dist/static'),
ignore: ['.*']
}
]),
new CleanWebpackPlugin([path.join(__dirname, 'dist')]),
],
devtool: 'eval-source-map', // 指定加source-map的方式
devServer: {
contentBase: path.join(__dirname, "dist"), //靜態文件根目錄
port: 3824, // 端口
host: 'localhost',
overlay: true,
compress: false // 服務器返回瀏覽器的時候是否啓動gzip壓縮
},
watch: true, // 開啓監聽文件更改,自動刷新
watchOptions: {
ignored: /node_modules/, //忽略不用監聽變動的目錄
aggregateTimeout: 500, //防止重複保存頻繁從新編譯,500毫米內重複保存不打包
poll:1000 //每秒詢問的文件變動的次數
},
}
複製代碼
在命令行下用如下命令安裝loader
和依賴的插件,生成徹底的package.json
項目依賴樹。java
npm install extract-text-webpack-plugin@next --save-dev
npm i style-loader css-loader postcss-loader --save-dev
npm i less less-loader --save-dev
npm i node-sass sass-loader --save-dev
npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 --save-dev
npm i file-loader url-loader --save-dev
npm i html-webpack-plugin ---save-dev
npm i clean-webpack-plugin --save-dev
npm i copy-webpack-plugin --save-dev
npm run dev
複製代碼
默認打開的頁面是index.html
頁面,能夠加上/page.html來打開page頁面看效果。 PS: 關於loader
的詳細說明能夠參考webpack3.x
的學習介紹,上面配置中須要注意的是多頁面的公共庫的引入採用的是vendor
+暴露全局變量的方式,其實這種方式有諸多弊端,而webpack4
針對這種狀況設置了新的API,有興趣的話,就繼續看下面的高級配置吧。node
包含如下幾個方面:webpack
CSS
和JS
的TreeShaking
來減小無用代碼,針對JS
須要對已有的uglifyjs
進行一些自定義的配置(生產環境配置)optimization.SplitChunksPlugin
)提取重用代碼,減少打包文件。(代替commonchunkplugin
,生產和開發環境都須要)HappyPack
進行javascript
的多進程打包操做,提高打包速度,並增長打包時間顯示。(生產和開發環境都須要)webpack.dll.config.js
文件打包經常使用類庫到dll中,使得開發過程當中基礎模塊不會重複打包,而是去動態鏈接庫裏獲取,代替上一節使用的vendor
。(注意這個是在開發環境使用,生產環境打包對時間要求並不高,後者每每是項目持續集成的一部分)webpack3
新增的做用域提高會默認在production
模式下啓用,不用特別配置,但只有在使用ES6模塊才能生效。關於第四點,須要在package.json中的script中增長腳本: "build:dll": "webpack --config webpack.dll.config.js --mode development",
git
補充安裝插件的命令行:es6
npm i purify-css purifycss-webpack -D // 用於css的tree-shaking
npm i webpack-parallel-uglify-plugin -D // 用於js的tree-shaking
npm i happypack@next -D //用於多進程打包js
npm i progress-bar-webpack-plugin -D //用於顯示打包時間和進程
npm i webpack-merge -D //優化配置代碼的工具
npm i optimize-css-assets-webpack-plugin -D //壓縮CSS
npm i chalk -D
npm install css-hot-loader -D // css熱更新
npm i mini-css-extract-plugin -D
npm i cross-env -D
複製代碼
TreeShaking
須要增長的配置代碼,這一塊參考webpack
文檔,須要三方面因素,分別是:github
ES6
模塊(import/export
)package.json
文件中聲明sideEffects
指定能夠treeShaking
的模塊UglifyJSPlugin
,多入口下用WebpackParallelUglifyPlugin
(這是下面的配置代碼作的事情)/*最上面要增長的聲明變量*/
const glob = require('glob')
const PurifyCSSPlugin = require('purifycss-webpack')
const WebpackParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
/*在`plugins`配置項中須要增長的兩個插件設置*/
new PurifyCSSPlugin({
paths: glob.sync(path.join(__dirname, 'src/*.html'))
}),
new WebpackParallelUglifyPlugin({
uglifyJS: {
output: {
beautify: false, //不須要格式化
comments: false //不保留註釋
},
compress: {
warnings: false, // 在UglifyJs刪除沒有用到的代碼時不輸出警告
drop_console: true, // 刪除全部的 `console` 語句,能夠兼容ie瀏覽器
collapse_vars: true, // 內嵌定義了可是隻用到一次的變量
reduce_vars: true // 提取出出現屢次可是沒有定義成變量去引用的靜態值
}
}
// 有興趣能夠探究一下使用uglifyES
}),
複製代碼
關於ES6
模塊這個事情,上文的第六點也提到了只有ES6
模塊寫法才能用上最新的做用域提高的特性,首先webpack4.x
並不須要額外修改babelrc
的配置來實現去除無用代碼,這是從webpack2.x
升級後支持的,改用sideEffect
聲明來實現。但做用域提高仍然須要把babel
配置中的module
轉換去掉,修改後的.babelrc
代碼以下:
{
"presets": [["env", {"loose": true, "modules": false}], "stage-0"]
}
複製代碼
但這個時候會發現import
引入樣式文件就被去掉了……只能使用require
來改寫了。
打包DLL
第三方類庫的配置項,用於開發環境:
webpack.dll.config.js
配置文件具體內容:const path = require('path')
const webpack = require('webpack')
const pkg = require('../package.json')
/** * 儘可能減少搜索範圍 * target: '_dll_[name]' 指定導出變量名字 */
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
vendor: Object.keys(pkg.dependencies)
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].dll.js',
library: '_dll_[name]' // 全局變量名,其餘模塊會今後變量上獲取裏面模塊
},
// manifest是描述文件
plugins: [
new webpack.DllPlugin({
name: '_dll_[name]',
path: path.join(__dirname, 'dist', 'manifest.json'),
context: path.resolve(__dirname, '../')
})
]
}
複製代碼
webpack.config.js
中增長的配置項:/*找到上一步生成的`manifest.json`文件配置到`plugins`裏面*/
new webpack.DllReferencePlugin({
manifest: require(path.join(__dirname, '..', 'dist', 'manifest.json')),
}),
複製代碼
多文件入口的公用代碼提取插件配置:
/*webpack4.x的最新優化配置項,用於提取公共代碼,跟`entry`是同一層級*/
optimization: {
splitChunks: {
cacheGroups: {
commons: {
chunks: "initial",
name: "common",
minChunks: 2,
maxInitialRequests: 5,
minSize: 0
}
}
}
}
/*針對生成HTML的插件,需增長common,也去掉上一節加的vendor*/
new HtmlWebpackPlugin({
template: path.resolve(__dirname,'src','index.html'),
filename:'index.html',
chunks:['index', 'common'],
vendor: './vendor.dll.js', //與dll配置文件中output.fileName對齊
hash:true,//防止緩存
minify:{
removeAttributeQuotes:true//壓縮 去掉引號
}
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname,'src','page.html'),
filename:'page.html',
chunks:['page', 'common'],
vendor: './vendor.dll.js', //與dll配置文件中output.fileName對齊
hash:true,//防止緩存
minify:{
removeAttributeQuotes:true//壓縮 去掉引號
}
}),
複製代碼
PS: 這一塊要多注意,對應入口的HTML
文件也要處理,關鍵是自定義的vendor
項,在開發環境中引入到html
中
HappyPack
的多進程打包處理:
/*最上面要增長的聲明變量*/
const HappyPack = require('happypack')
const os = require('os') //獲取電腦的處理器有幾個核心,做爲配置傳入
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
const ProgressBarPlugin = require('progress-bar-webpack-plugin')
/*在`module.rules`配置項中須要更改的`loader`設置*/
{
test: /\.jsx?$/,
loader: 'happypack/loader?id=happy-babel-js',
include: [path.resolve('src')],
exclude: /node_modules/,
},
/*在`plugins`配置項中須要增長的插件設置*/
new HappyPack({ //開啓多線程打包
id: 'happy-babel-js',
loaders: ['babel-loader?cacheDirectory=true'],
threadPool: happyThreadPool
}),
new ProgressBarPlugin({
format: ' build [:bar] ' + chalk.green.bold(':percent') + ' (:elapsed seconds)'
})
複製代碼
PS:要記住這種使用方法下必定要在根目錄下加.babelrc
文件來設置babel
的打包配置。
開發環境的代碼熱更新: 其實針對熱刷新,還有兩個方面要說起,一個是html文件裏面寫代碼的熱跟新(這個對於框架不須要,若是要實現,建議使用glup
,後面有代碼),一個是寫的樣式代碼的熱更新,這兩部分也要加進去。讓咱們一塊兒看看熱更新須要增長的配置代碼:
/*在`devServer`配置項中需增長的設置*/
hot:true
/*在`plugins`配置項中須要增長的插件設置*/
new webpack.HotModuleReplacementPlugin(), //模塊熱更新
new webpack.NamedModulesPlugin(), //模塊熱更新
複製代碼
在業務代碼中要作一些改動,一個比較low
的例子爲:
if(module.hot) { //設置消息監聽,從新執行函數
module.hot.accept('./hello.js', function() {
div.innerHTML = hello()
})
}
複製代碼
但仍是不能實如今html
修改後自動刷新頁面,這裏有個概念是熱更新不是針對頁面級別的修改,這個問題有一些解決方法,但目前都不是很完美,能夠參考這裏,如今針對CSS的熱重載有一套解決方案以下,須要放棄使用上文提到的ExtractTextWebapckPlugin
,引入mini-css-extract-plugin
和hot-css-loader
來實現,前者在webpack4.x上與hot-css-loader
有報錯,讓咱們改造一番:
/*最上面要增長的聲明變量*/
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
/*在樣式的`loader`配置項中需增長的設置,實現css熱更新,以css爲例,其餘能夠參照個人倉庫來寫*/
{
test: /\.css$/,
use: ['css-hot-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'],
include: [resolve('src')], //限制範圍,提升打包速度
exclude: /node_modules/
}
/*在`plugins`配置項中須要增長的插件設置,注意這裏不能寫[hash],不然沒法實現熱跟新,若是有hash須要,能夠開發環境和生產環境分開配置*/
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
複製代碼
用於生產環境壓縮css
的插件,看官方文檔說明,樣式文件壓縮沒有內置的,因此暫時引用第三方插件來作,如下是配置示例。
/*要增長的聲明變量*/
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
/*在`plugins`配置項中須要增長的插件設置*/
new OptimizeCSSPlugin({
cssProcessorOptions: {safe: true}
})
複製代碼
在進階部分咱們對webpack
配置文件根據開發環境和生產環境的不一樣作了分別的配置,所以有必要分紅兩個文件,而後發現重複的配置代碼不少,做爲有代碼潔癖的人不能忍,果斷引入webpack-merge
,來把相同的配置抽出來,放到build/webpack.base.js
中,然後在build/webpack.dev.config.js
(開發環境)和build/webpack.prod.config.js
(生產環境)中分別引用,在這個過程當中也要更改以前文件的路徑設置,以避免打包或者找文件的路徑出錯,同時將package.json
中的腳本命令修改成:
"scripts": {
"build": "cross-env NODE_ENV='production' webpack --config build/webpack.prod.config.js --mode production",
"dev": "cross-env NODE_ENV='development' webpack-dev-server --open --config build/webpack.dev.config.js --mode development",
"dll": "webpack --config build/webpack.dll.config.js --mode production",
"start": "npm run dll && npm run dev",
"prod": "npm run dll && npm run build"
}
複製代碼
接下來就是代碼的重構過程,這個過程其實我建議你們本身動手作一作,就能對webpack
配置文件結構更加清晰。
build
文件夾下的webpack.base.js
文件:
'use strict'
const path = require('path');
const chalk = require('chalk');
const ProgressBarPlugin = require('progress-bar-webpack-plugin')
const HappyPack = require('happypack')
const os = require('os')
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
function assetsPath(_path_) {
let assetsSubDirectory;
if (process.env.NODE_ENV === 'production') { // 這裏須要用cross-env來注入Node變量
assetsSubDirectory = 'static' //可根據實際狀況修改
} else {
assetsSubDirectory = 'static'
}
return path.posix.join(assetsSubDirectory, _path_)
}
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
index: './src/index.js',
page: './src/page.js'
},
output:{
path: resolve('dist'),
filename:'[name].[hash].js'
},
resolve: {
extensions: [".js",".css",".json"],
alias: {} //配置別名能夠加快webpack查找模塊的速度
},
module: {
// 多個loader是有順序要求的,從右往左寫,由於轉換的時候是從右往左轉換的
rules:[
{
test: /\.css$/,
use: ['css-hot-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'],
include: [resolve('src')], //限制範圍,提升打包速度
exclude: /node_modules/
},
{
test:/\.less$/,
use: ['css-hot-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader'],
include: [resolve('src')],
exclude: /node_modules/
},
{
test:/\.scss$/,
use: ['css-hot-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'],
include: [resolve('src')],
exclude: /node_modules/
},
{
test: /\.jsx?$/,
loader: 'happypack/loader?id=happy-babel-js',
include: [resolve('src')],
exclude: /node_modules/,
},
{ //file-loader 解決css等文件中引入圖片路徑的問題
// url-loader 當圖片較小的時候會把圖片BASE64編碼,大於limit參數的時候仍是使用file-loader 進行拷貝
test: /\.(png|jpg|jpeg|gif|svg)/,
use: {
loader: 'url-loader',
options: {
name: assetsPath('images/[name].[hash:7].[ext]'), // 圖片輸出的路徑
limit: 1 * 1024
}
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
optimization: { //webpack4.x的最新優化配置項,用於提取公共代碼
splitChunks: {
cacheGroups: {
commons: {
chunks: "initial",
name: "common",
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
}
}
}
},
plugins: [
new HappyPack({
id: 'happy-babel-js',
loaders: ['babel-loader?cacheDirectory=true'],
threadPool: happyThreadPool
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
}),
new ProgressBarPlugin({
format: ' build [:bar] ' + chalk.green.bold(':percent') + ' (:elapsed seconds)'
}),
]
}
複製代碼
webpack.dev.config.js
文件內容:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin') // 生成html的插件
const webpack = require('webpack')
const baseConfig = require('./webpack.base')
const merge = require('webpack-merge')
const devWebpackConfig = merge(baseConfig, {
output:{
publicPath: '/'
},
devtool: 'eval-source-map', // 指定加source-map的方式
devServer: {
inline:true,//打包後加入一個websocket客戶端
hot:true,//熱加載
contentBase: path.join(__dirname, "..", "dist"), //靜態文件根目錄
port: 3824, // 端口
host: 'localhost',
overlay: true,
compress: false // 服務器返回瀏覽器的時候是否啓動gzip壓縮
},
watchOptions: {
ignored: /node_modules/, //忽略不用監聽變動的目錄
aggregateTimeout: 500, //防止重複保存頻繁從新編譯,500毫米內重複保存不打包
poll:1000 //每秒詢問的文件變動的次數
},
plugins: [
// 多入口的html文件用chunks這個參數來區分
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '..', 'src','index.html'),
filename:'index.html',
chunks:['index', 'common'],
vendor: './vendor.dll.js', //與dll配置文件中output.fileName對齊
hash:true,//防止緩存
minify:{
removeAttributeQuotes:true//壓縮 去掉引號
}
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '..', 'src','page.html'),
filename:'page.html',
chunks:['page', 'common'],
vendor: './vendor.dll.js', //與dll配置文件中output.fileName對齊
hash:true,//防止緩存
minify:{
removeAttributeQuotes:true//壓縮 去掉引號
}
}),
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, '..', 'dist', 'manifest.json')
}),
new webpack.HotModuleReplacementPlugin(), //HMR
new webpack.NamedModulesPlugin() // HMR
]
})
module.exports = devWebpackConfig
複製代碼
webpack.dev.config.js
文件內容:
'use strict'
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin') // 複製靜態資源的插件
const CleanWebpackPlugin = require('clean-webpack-plugin') // 清空打包目錄的插件
const HtmlWebpackPlugin = require('html-webpack-plugin') // 生成html的插件
const webpack = require('webpack')
const baseConfig = require('./webpack.base')
const merge = require('webpack-merge')
const glob = require('glob')
const PurifyCSSPlugin = require('purifycss-webpack')
const WebpackParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = merge(baseConfig, {
output:{
publicPath: './' //這裏要放的是靜態資源CDN的地址(只在生產環境下配置)
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '..', 'src', 'index.html'),
filename:'index.html',
chunks:['index', 'common'],
hash:true,//防止緩存
minify:{
removeAttributeQuotes:true//壓縮 去掉引號
}
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '..', 'src', 'page.html'),
filename:'page.html',
chunks:['page', 'common'],
hash:true,//防止緩存
minify:{
removeAttributeQuotes:true//壓縮 去掉引號
}
}),
new CopyWebpackPlugin([
{
from: path.join(__dirname, '..', 'static'),
to: path.join(__dirname, '..', 'dist', 'static'),
ignore: ['.*']
}
]),
new CleanWebpackPlugin(['dist'], {
root: path.join(__dirname, '..'),
verbose: true,
dry: false
}),
new OptimizeCSSPlugin({
cssProcessorOptions: {safe: true}
}),
new PurifyCSSPlugin({
paths: glob.sync(path.join(__dirname, '../src/*.html'))
}),
new WebpackParallelUglifyPlugin({
uglifyJS: {
output: {
beautify: false, //不須要格式化
comments: false //不保留註釋
},
compress: {
warnings: false, // 在UglifyJs刪除沒有用到的代碼時不輸出警告
drop_console: true, // 刪除全部的 `console` 語句,能夠兼容ie瀏覽器
collapse_vars: true, // 內嵌定義了可是隻用到一次的變量
reduce_vars: true // 提取出出現屢次可是沒有定義成變量去引用的靜態值
}
}
}),
]
})
複製代碼
多說一句,就是實現JS打包的treeShaking
還有一種方法是編譯期分析依賴,利用uglifyjs來完成,這種狀況須要保留ES6模塊才能實現,所以在使用這一特性的倉庫中,.babelrc
文件的配置爲:"presets": [["env", { "modules": false }], "stage-0"]
,就是打包的時候不要轉換模塊引入方式的含義。
接下來就能夠運行npm start
,看一下進階配置後的成果啦,吼吼,以後只要不進行build
打包操做,經過npm run dev
啓動,不用重複打包vendor
啦。生產環境打包使用的是npm run build
。
以上就是對webpack4.x
配置的踩坑過程,期間參考了大量谷歌英文資料,但願能幫助你們更好地掌握wepback
最新版本的配置,以上內容親測跑通,有問題的話,歡迎加我微信(kashao3824)討論,到github
地址提issue
也可,歡迎fork/star
。
最新更改:
common
會重複打包已有dll
庫的問題dll
庫會自動根據package.json
中的配置項生成dll
如今是生產環境打包模式,而且vendor.dll.js
如今在生產環境下也會注入HTML
模板中npm run prod
process.env.NODE_ENV
在打包過程當中取不到的問題 issue2