Webpack 是一個JavaScript應用程序的打包模塊化工具.Webpack裏一切文件都是模塊,處理應用程序時,它會遞歸構建程序中各個模塊的依賴關係圖, 最後將這些模塊打包成一個或者多個bundle。css
入口起點指示 webpack 應該使用哪一個模塊,來做爲構建其內部依賴圖的開始。進入入口起點後,webpack 會找出有哪些模塊和庫是入口起點(直接和間接)依賴的。html
output 屬性告訴 webpack 在哪裏輸出它所建立的 bundles,以及如何命名這些文件,默認值爲 ./dist
。基本上,整個應用程序結構,都會被編譯到你指定的輸出路徑的文件夾中。能夠經過在配置中指定一個 output
字段,來配置這些處理過程。node
loade
讓 webpack 可以去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 能夠將全部類型的文件轉換爲 webpack 可以處理的有效模塊,而後就能夠利用 webpack 的打包能力,對它們進行處理。本質上,webpack loader 將全部類型的文件,轉換爲應用程序的依賴圖(和最終的 bundle)能夠直接引用的模塊。react
loader 被用於轉換某些類型的模塊,而插件則能夠用於執行範圍更廣的任務。插件的範圍包括,從打包優化和壓縮,一直到從新定義環境中的變量。插件接口功能極其強大,能夠用來處理各類各樣的任務。webpack
經過選擇 development
或 production
之中的一個,來設置 mode
參數,能夠啓用相應模式下的 webpack 內置的優化。web
能夠經過一個JavaScript文件導出Webpack的配置:typescript
module.exports = {
mode: "development", // 模式
entry: {}, // 入口
output: {}, // 輸出
resolve: {}, // 解析
module: {}, // 模塊
plugins: [], // 插件
}
複製代碼
mode
的取值有development
和production
。經過設置mode
,webpack在打包時會使用相應模式的內置優化,並process.env.NODE_ENV
設置爲對應的值。json
entry是應用的入口,能夠傳入一個字符串、數組或者對象。若是傳入一個字符串或字符串數組,chunk 會被命名爲 main
。若是傳入一個對象,則每一個鍵(key)會是 chunk 的名稱,該值描述了 chunk 的入口起點。api
module.exports = {
// ...
entry: {
app: "./src/index.js"
}
}
複製代碼
output
能夠控制 webpack 如何向硬盤寫入編譯文件。即便能夠存在多個入口
起點,但只指定一個輸出
配置。數組
output.path
: 指定打包後內容的輸出目錄
output.filename
: 配置每一個輸出bundle
的名稱,可使用模板字符串配置輸出。
模板 | 描述 |
---|---|
[hash] |
模塊標識符的hash |
[chunkhash] |
chunk 內容的hash |
[name] |
模塊名稱 |
[id] |
模塊標識符 |
[query] |
模塊的query |
output.chunkFilename
:配置非入口chunk
文件的名稱,默認[id].js
,與filename
選項一致可使用模板字符串。
output.publicPath
:指定在瀏覽器中所引用的此輸出目錄對應的公開 URL。
module.export = {
// ...
output: {
path: "./dist",
publicPath: "https://example.com",
filename: "[name].[chunkhash].js",
chunkFilename: "[name].[chunkhash].js"
}
}
複製代碼
resolve
設置模塊如何被解析。
resolve.alias
:設置導入模塊時的別名resolve.modules
:設置模塊解析時搜索的目錄module.exports = {
// ...
resolve: {
alias: {
"@src": "./src/"
},
modules: ["./node_modules"]
}
}
複製代碼
module
設置webpack如何處理不一樣類型的模塊。
module.rules
:配置規則數組。在建立模塊時,匹配對應的規則並應用loader
處理模塊。規則(Rule
)的配置:
rule.test
:匹配模塊文件路徑rule.include
:匹配目錄下的文件rule.exclude
:匹配不在目錄下的文件rule.use
:使用loader
,loader
應用順序爲從右到左module.exports = {
// ...
rules: [{
test: /.js$/,
include: ['./src'],
use: ["babel-loader"]
}]
}
複製代碼
plugins
設置打包過程當中使用的插件。
module.exports = {
// ...
plugins: []
}
複製代碼
設置source maps
如何生成,開發時能夠將此選項設置爲cheap-module-eval-source-map
。
module.exports = {
// ...
devtool: "cheap-module-eval-source-map"
}
複製代碼
設置webpack-dev-server
使用時的選項,能夠配置監聽端口、代理等。
const path = require("path")
module.exports = {
// ...
devServer: {
host: "0.0.0.0",
contentBase: path.resolve(__dirname, "build"),
hot: true, // 開啓模塊熱替換
historyApiFallback: true, // 使用index.html頁面來代替404響應,使用HTML5 History API時可將該選項設置爲true,例如react-router
proxy: {
'/api': 'http://127.0.0.1:3000'
}
}
}
複製代碼
loader
用於解析CSS
的loader
通常有:style-loader
、css-loader
、postcss-loader
、less-loader
和sass-loader
。
style-loader
:經過注入<style>
標籤將CSS添加到DOMcss-loader
:解釋@import
和 url()
,會 import/require()
後再解析它們。css-loader
前應用了loader
須要指定importLoaders
選項postcss-loader
:應用postcss
less-loader
:解析less
sass-loader
:解析sass
module.exports = {
// ...
module: {
rules: [{
test: /.less$/,
include: ["./src"],
use: [
"style-loader",
{
loader: "css-loader",
options: {
importLoaders: 2
}
},
"postcss-loader",
"less-loader"
]
}]
}
}
複製代碼
babel-loader
:babel-loader
基於babel
,用於解析JavaScript
文件。babel
有豐富的預設和插件,babel
的配置能夠直接寫到options
裏或者單獨寫道配置文件裏。幾個babel
經常使用的預設和插件:
@babel/preset-env
:用於轉換最新的JavaScript
代碼、爲低版本瀏覽器提供polyfill
@babel/preset-react
:用於解析jsx
內容,該預設包含了@babel/plugin-syntax-jsx
、@babel/plugin-transform-react-jsx
和@babel/plugin-transform-react-display-name
三個插件。當指定了development
選項時,還額外包含@babel/plugin-transform-react-jsx-self
和@babel/plugin-transform-react-jsx-source
兩個插件@babel/preset-typescript
:用於解析typescript
內容,該預設僅包含@babel/plugin-transform-typescript
插件。在解析typescript
內容時,該預設會直接把typescript
相關的內容去掉@babel/plugin-proposal-class-properties
:用於解析類屬性的插件@babel/plugin-proposal-object-rest-spread
:用於解析析構對象的插件@babel/plugin-transform-runtime
:用於複用babel
內置的helper
代碼從而減少代碼體積babel
經常使用的預設有preset-env
、preset-react
、preset
module.export = {
// ...
module: {
rules: [{
test: /.js$/,
include: ["./src/"],
use: [{
loader: "babel-loader",
options: {
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread",
]
}
}]
}]
}
}
複製代碼
除了CSS
和JavaScript
資源外,項目裏還有其餘的資源,例如圖片、字體等。對於這類資源,能夠經過file-loader
或url-loader
解析。
file-loader
:告訴Webpack
引用的模塊是一個文件,並返回其打包後的url
url-loader
:做用與file-loader
相似,但當文件大小(單位 byte)低於指定的限制時,能夠返回一個 DataURL。module.exports = {
// ...
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8192
}
}]
}]
}
}
複製代碼
copy-webpack-plugin
copy-webpack-plugin
用於打包時複製文件。
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
// ...
plugins: [
new CopyWebpackPlugin({
{
from: "./public",
to: "./build/"
}
})
]
}
複製代碼
html-webpack-plugin
生成一個 HTML5 文件,包括使用 script
標籤的 body 中的全部 webpack 包。
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
chunks: ["app"]
})
]
};
複製代碼
add-asset-html-webpack-plugin
插入一個JavaScript
或者CSS
資源到html-webpack-plugin
生產的html
頁面中。使用DLL
時,能夠經過該插件將生成的JavaScript
文件插入到頁面中。
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
const path = require("path")
module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin(),
new AddAssetHtmlPlugin({
filepath: path.resolve(__dirname, './dlls/*.dll.js'),
outputPath: "dlls",
publicPath: "/dlls"
})
]
};
複製代碼
clean-webpack-plugin
clean-webpack-plugin
能夠清理文件,能夠用於打包時清理以前打包的文件。
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
// ...
plugins: [
new CleanWebpackPlugin()
]
};
複製代碼
mini-css-extract-plugin
將CSS提取到單獨的文件中,爲每一個包含CSS的JS文件建立一個CSS文件,同時該插件支持CSS和SourceMap的按需加載。使用該插件時,style-loader
須要替換爲該插件提供的loader
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// ...
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, // 須要替換 style-loader
{
loader: "css-loader",
options: {
importLoaders: 1
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "static/css/[name].[chunkhash:8].css",
chunkFilename: "static/css/[name].[chunkhash:8].chunk.css"
})
]
};
複製代碼
webpack.HotModuleReplacementPlugin
模塊熱替換插件,開啓HMR。能夠和webpack.NamedModulesPlugin
搭配使用,顯示模塊的相對路徑,建議用於開發環境。
const webpack = require('webpack');
module.exports = {
// ...
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
]
};
複製代碼
webpack.DefinePlugin
建立一個在編譯時能夠配置的全局常量。
const webpack = require('webpack');
module.exports = {
// ...
plugins: [
new webpack.DefinePlugin({
VERSION: JSON.stringify("0.0.1")
})
]
};
複製代碼
由於這個插件直接執行文本替換,給定的值必須包含字符串自己內的實際引號。一般,有兩種方式來達到這個效果,使用'"production"'
, 或者使用 JSON.stringify('production')
。
webpack.DllPlugin
和 webpack.DllReferencePlugin
DllPlugin和DllReferencePlugin提供了一種拆分包的方法,能夠極大地提升構建時間性能。
// 製做dll
const webpack = require("webpack");
const path = require("path");
module.exports = {
mode: "production",
entry: {
react: ["react", "react-dom"],
antd: ["antd"],
utils: ["lodash", "moment"]
},
output: {
path: "./dlls",
filename: "[name].dll.js",
library: "[name]_[hash]"
},
resolve: {
extensions: [".js", ".jsx"],
modules: ["./node_modules"]
},
plugins: [
new webpack.DllPlugin({
path: path.resolve(__dirname, "./dlls/[name].manifest.json"),
name: "[name]_[hash]"
})
]
};
複製代碼
// 使用dll
const webpack = require("webpack");
const path = require("path");
module.exports = {
// ...
plugins: [
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, "./dlls/react.manifest.json"),
}),
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, "./dlls/antd.manifest.json"),
}),
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, "./dlls/utils.manifest.json"),
}),
new AddAssetHtmlWebpackPlugin({
filepath: path.resolves(__dirname, './dlls/*.dll.js'),
outputPath: "dlls",
publicPath: "/dlls"
})
]
};
複製代碼