關於 webpack 相關的文章太多了,何不一塊兒從零開始手寫一個配置呢?css
真的3秒能打包一個three.js項目嗎?真的,後面會提供源文件地址哦。html
要打包的項目是這個樣子的。 前端
關於 three.js
的安裝和使用部分都省略。node
首先是最基礎的。咱們須要安裝webpack
cross-env
目前最流行的運行跨平臺設置和使用環境變量的腳本webpack
+ webpack-cli
+ webpack-dev-server
:三'賤'客,項目必備參考常規webpack配置結構須要3個最基礎文件:git
webpack.base.js
webpack.dev.js
webpack.prod.js
固然,須要把 dev
或 prod
中的配置和 base
的配置合併起來,安裝個webpack-merge
吧。github
而後配置一下最熟悉的腳本運行環節吧。經過--config
來對標配置文件,通cross-env
設置環境變量web
"dev": "cross-env NODE_ENV=dev webpack-dev-server --config script/webpack.dev.js",
"build": "cross-env NODE_ENV=prod webpack --config script/webpack.prod.js"
複製代碼
好的,初期準備工做都OK開始配置環節。npm
首先是webpack的出入口。出口設置爲 dist 環節簡單直接上代碼。json
{
entry: './src/index.js',
output: {
filename: '[name].[hash:8].js',
path: rootResolve('dist'),
publicPath: '/'
},
}
複製代碼
順便配置下別名。依然能夠直接上代碼
resolve: {
extensions: ['.js', '.json'],
alias: {
'@': rootResolve('src'),
'@assets': rootResolve('src/assets'),
}
}
複製代碼
而後是關鍵環節:loader
和 plugins
關於 loader
:
less
less-loader
解析 less
由於 webpack 只能讀懂jspostcss-loader
加上瀏覽器前綴css-loader
解析css代碼中的 url
、@import
語法MiniCssExtractPlugin.loader
生成 .css
文件babel-loader
,關於 babel
文章太多了,暫略
HappyPack
進行優化加速thread-loader
呢? (由於名字很差聽 - -!
怪我咯)url-loader
咯。而後 loader
配置就是這樣的
{
test: /\.less$/,
exclude: /(node_modules|bower_components)/,
loaders: [{
loader: MiniCssExtractPlugin.loader,
options: {
esModule: true,
hmr: process.env.NODE_ENV === 'dev', // 熱更新
// publicPath: '../',
}
}, 'css-loader', 'postcss-loader', 'less-loader']
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
loader: 'happypack/loader',
options: {
id: 'babel',
}
},
{
test: /\.(png|jpe?g|gif)(\?.*)?$/,
use: [{
loader: 'url-loader',
options: {
limit: 8192,
name: 'assets/img/[hash:8].[ext]'
}
}]
}
複製代碼
關於插件部分,首先是配合上面 loader
的相關插件:HappyPack
和 MiniCssExtractPlugin
new MiniCssExtractPlugin({
filename: "css/[name].[hash:8].css", // css 路徑
}),
new HappyPack({
id: 'babel',
loaders: [{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
cacheDirectory: true
}
}]
})
複製代碼
固然,我想知道運行和打包的進度: ProgressPlugin
,順便弄個 DefinePlugin
工程化必備插件。最後webpack生成後的代碼注入不能少了 HtmlWebpackPlugin
而後 base
文件的插件結構是這樣的
plugins: [
new webpack.ProgressPlugin(),
new webpack.DefinePlugin({
NODE_ENV: JSON.stringify(process.env.NODE_ENV), // 當前使用環境
VERSION: JSON.stringify('0.1.0'),
}),
new MiniCssExtractPlugin({
filename: "css/[name].[hash:8].css", // css 路徑
// chunkFilename: "[id].css",
}),
new HappyPack({
id: 'babel',
loaders: [{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
cacheDirectory: true
}
}]
}),
new HtmlWebpackPlugin({ template: './src/index.html' })
]
複製代碼
首先開發環境 api 代理必不可少。那麼就是 devServer.proxy
了,順便再定義下開發環境端口號。
devServer: {
contentBase: path.join(__dirname, "dist"),
compress: true,
port: 3333
}
複製代碼
目前也沒有太多事情,那麼 merge 下再配個 HotModuleReplacementPlugin
吧
merge(base, {
mode: 'development',
plugins: [
],
devServer: {
contentBase: rootResolve("src"),
compress: true,
port: 3333
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
})
複製代碼
打包環境主要作了這幾件事情
首先是 dll
webpack.dll.config.js
manifest.dll.json
那麼 webpack.dll.config.js
內容應該是這樣的
{
// 你想要打包的模塊的數組
entry: {
vendor: ['three']
},
output: {
filename: '[name].dll.js',
path: distResolve('dll'), // 打包後文件輸出的位置
library: '[name]_library'
// 這裏須要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
},
plugins: [
new webpack.DllPlugin({
name: '[name]_library',
path: distResolve('dll/manifest.dll.json'),
context: __dirname
})
]
}
複製代碼
DllReferencePlugin
+ json文件
把 dll模塊的詳細要點告訴 webpack在 prod
文件中添加 plugins
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require(distResolve('./dll/manifest.dll.json'))
})
複製代碼
"dll": "webpack --config script/webpack.dll.config.js",
複製代碼
運行下 npm run dll
,在 dist/dll
目錄下生成dll相關文件,那麼 dll
配置也完成了。順便作一些清理工做,用下 CleanWebpackPlugin
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [
'assets', 'js', 'css', 'index.html', '*.js',
'!manifest.dll.json', '!vendor.dll.js' // 不刪除 dll 文件
],
})
複製代碼
而後是代碼優化,其實當 mode: 'production'
時已經作了不少代碼優化相關的事情了。(我無論,我就是要優化 - -!
)
作一下 js的並行壓縮吧
optimization: {
minimizer: [
new TerserWebpackPlugin({
parallel: true, // 啓用並行壓縮
cache: true, // 啓用緩存
}),
new OptimizeCssAssetsPlugin({ // 壓縮css
cssProcessorOptions: {
safe: true
}
})
],
runtimeChunk: true, // 自動拆分runtime文件
splitChunks: {
chunks: 'async',
minSize: 30000,
automaticNameDelimiter: '~',
automaticNameMaxLength: 30,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
},
}
複製代碼
歐耶,再配置下js的打包後路徑就行了
output: { // JS 路徑
path: distResolve(),
filename: 'js/[id].[chunkhash].js',
chunkFilename: 'js/[name].[chunkhash].js'
},
複製代碼
最後 merge
下 base
配置。在 dev
時作過了... 省略。
至此,Webpack配置已經大部分完成了,運行npm run build
打包代碼,一、二、3。 3秒打包完成了。
爲何只須要3秒呢?雖然上面的配置確實作了不少優化,可是大部分事情都被表象迷惑了,具體爲什麼下一章見。