接觸webpack是好久之前的事情了,最近看了下webpack沒想到都到4了。
webpack 是一個現代 JavaScript 應用程式的靜態模組打包器(module bundler).
會建立1個依賴關係圖(dependency graph),包含所有依賴的模組,然後將模組打包成1個或多個bundle.
webpack4 仍然支援高度可配,但完全可以不用配置檔案了(基於mode)。
安裝
淘寶源:npm config set registry https://registry.npm.taobao.org
升級npm:npm i npm -g
安裝webpack:npm i -D webpack webpack-cli webpack-dev-server
執行webpack:npx webpack
(Node 8.2+ 版本提供的npx
命令)
基本特性
核心配置:
- 入口(entry):
- 輸出(output):
- loader:
- 外掛(plugins):
Entry
入口起點(entry point)指示 webpack 應該使用哪個模組,來作為構建其內部依賴圖的開始。
可以通過在 webpack 配置中配置 entry 屬性,來指定一個入口起點(或多個入口起點)。預設值為 ./src/index.js
webpack.config.js
module.exports = {
entry: {
main: `./src/index.js`
},
};
Output
output 屬性告訴 webpack 在哪裡輸出它所建立的 bundles,以及如何命名這些檔案,預設值為./dist/[name].js
webpack.config.js
const path = require(`path`);
module.exports = {
entry: `./src/index.js`,
output: {
path: path.resolve(__dirname, `dist`),
filename: `[name].js`
}
};
Loader
loader 讓 webpack 能夠去處理那些非 JavaScript 檔案(webpack 自身只理解 JavaScript)。
loaders 有2個核心引數:
- test 屬性,用於標識出需要轉換的某個或某些檔案。
- use 屬性,表示進行轉換時,應該使用哪個 loader。
const path = require(`path`);
const config = {
output: {
filename: `bundle.js`
},
module: {
rules: [
{ test: /.txt$/, use: `raw-loader` }
]
}
};
module.exports = config;
Plugins
外掛的範圍包括,從打包優化和壓縮,一直到重新定義環境中的變數。外掛介面功能極其強大,可以用來處理各種各樣的任務。
webpack.config.js
const HtmlWebpackPlugin = require(`html-webpack-plugin`); // 通過 npm 安裝
const webpack = require(`webpack`); // 用於訪問內建外掛
const config = {
module: {
rules: [
{ test: /.txt$/, use: `raw-loader` }
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: `./src/index.html`})
]
};
module.exports = config;
Mode
通過選擇 development 或 production 之中的一個,來設定 mode 引數
webpack.config.js
module.exports = {
mode: `production`
};
mode.js
// webpack.development.config.js
module.exports = {
+ mode: `development`
- plugins: [
- new webpack.NamedModulesPlugin(),
- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),
- ]
}
// webpack.production.config.js
module.exports = {
+ mode: `production`,
- plugins: [
- new UglifyJsPlugin(/* ... */),
- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
- new webpack.optimize.ModuleConcatenationPlugin(),
- new webpack.NoEmitOnErrorsPlugin()
- ]
}
常用外掛
HtmlWebpackPlugin:
const HtmlWebpackPlugin = require(`html-webpack-plugin`);
new HtmlWebpackPlugin({ template: `src/index.html`, minify: true, hash: true })
CleanWebpackPlugin:
const CleanWebpackPlugin = require(`clean-webpack-plugin`);
new CleanWebpackPlugin([`dist`])
MiniCssExtractPlugin(ExtractTextPlugin):
new MiniCssExtractPlugin({ filename: "[name].css",chunkFilename: "[id].css" })
module: {
rules: [{
test: /.css$/,
use: [
MiniCssExtractPlugin.loader,
`css-loader`
]}
]
}
SplitChunksPlugin:
module.exports = {
mode: `development`,
entry: {
main: `./src/index.js`,
vendors: `lodash`
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
test: /[\/]node_modules[\/]/,
name: "vendors",
chunks: "initial"
}
}
}
}
}
配置示例
package
package.json
{
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"start": "webpack-dev-server --open",
"build": "webpack --config webpack.prod.js"
},
"devDependencies": {
"babel-loader": "^7.1.4",
"babel-preset-react": "^6.24.1",
"babel-plugin-import": "^1.7.0",
"clean-webpack-plugin": "^0.1.19",
"css-loader": "^0.28.11",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.4.0",
"webpack": "^4.8.3",
"webpack-cli": "^2.1.3",
"webpack-dev-server": "^3.1.4"
},
"dependencies": {
"antd": "^3.5.2",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"express": "^4.16.3",
"lodash": "^4.17.10",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-loadable": "^5.4.0",
"react-redux": "^5.0.7",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"redux": "^4.0.0",
"redux-logger": "^3.0.6",
"redux-promise": "^0.6.0",
"redux-saga": "^0.16.0",
"redux-thunk": "^2.2.0"
}
}
開發環境
const CleanWebpackPlugin = require(`clean-webpack-plugin`);
const HtmlWebpackPlugin = require(`html-webpack-plugin`);
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const path = require(`path`);
module.exports = {
mode: `development`,
entry: {
main: `./src/index.js`,
},
devtool: `inline-source-map`,
devServer: {
contentBase: `./dist`
},
output: {
path: path.resolve(__dirname, `dist`),
filename: `[name].js`,
},
module: {
rules: [{
test: /.css$/,
use: [
MiniCssExtractPlugin.loader,
`css-loader`
]
}, {
test: /.(js|jsx)$/,
loader: `babel-loader`,
options: {
presets: [`react`],
plugins: [
["import", { "libraryName": "antd", "style": "css" }]
]
},
exclude: /node_modules/
}]
},
plugins: [
new CleanWebpackPlugin([`dist`]),
new HtmlWebpackPlugin({ minify: true, hash: true }),
new MiniCssExtractPlugin({ filename: "[name].css", chunkFilename: "[id].css" })
],
optimization: {
splitChunks: {
cacheGroups: {
common: {
test: /[\/]node_modules[\/]/,
name: "common",
chunks: "initial",
enforce: true
},
}
}
}
};
生產環境
const CleanWebpackPlugin = require(`clean-webpack-plugin`);
const HtmlWebpackPlugin = require(`html-webpack-plugin`);
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const path = require(`path`);
module.exports = {
mode: `production`,
entry: {
main: `./src/index.js`,
},
devtool: `source-map`,
devServer: {
contentBase: `./dist`,
host: `192.168.0.75`
},
output: {
path: path.resolve(__dirname, `dist`),
filename: `[name].js`,
},
module: {
rules: [{
test: /.css$/,
use: [
MiniCssExtractPlugin.loader,
`css-loader`
]
}, {
test: /.(js|jsx)$/,
loader: `babel-loader`,
options: {
presets: [`react`],
plugins: []
},
exclude: /node_modules/
}]
},
plugins: [
new CleanWebpackPlugin([`dist`]),
new HtmlWebpackPlugin({ template: `src/index.html`, minify: true, hash: true }),
new MiniCssExtractPlugin({ filename: "[name].css", chunkFilename: "[id].css" })
],
externals: {
lodash: `_`,
react: `React`,
`react-dom`: `ReactDOM`,
antd: `antd`
},
optimization: {
splitChunks: {
cacheGroups: {
common: {
test: /[\/]node_modules[\/]/,
name: "common",
chunks: "initial",
enforce: true
},
}
}
}
};