前言
在上一篇文章中,我们对配置进行了抽离和优化,在这篇文章中,我们会进一步的完善和优化我们的template,这一篇文章的代码可以在vue3-webpack5-templatetag1.0.0中看到,现在开始吧
webpack配置完善
虽说已经添加了不少配置,但还是有很多功能没有用到,现在我们一个一个的来加上去
devtool
devtoool
控制是否生成以及如何生成sourcemap
,有很多值可以选择,开发环境下,为了加快构建速度,我们可以选择eval
,生产环境下,为了更高质量的sourcemap
,我们可以选择值为source-map
,不过相应的会降低打包速度,大家可以自己根据速度与质量来进行权衡。
对于devtool和接下来的一些配置,我们可以将它们放在config.js中统一管理
module.exports = {
dev: {
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: true,
errorOverlay: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'eval-cheap-module-source-map',
cssSourceMap: true
},
build: {
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: 'source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// yarn add --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `yarn run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
}
复制代码
mode
mode
是webpack内部的一个配置选项,告知 webpack 使用相应模式的内置优化
支持以下字符串值:
选项 | 描述 |
---|---|
development |
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development . 为模块和 chunk 启用有效的名。 |
production |
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production 。为模块和 chunk 启用确定性的混淆名称,FlagDependencyUsagePlugin ,FlagIncludedChunksPlugin ,ModuleConcatenationPlugin ,NoEmitOnErrorsPlugin 和 TerserPlugin 。 |
none |
不使用任何默认优化选项 |
如果没有设置,webpack 会给 mode
的默认值设置为 production
。我们在对应的环境中设置好对应的mode值即可
stats
用来控制打包后的bundle信息怎么显示,在dev环境中,我们一般使用 'errors-only
,不然每次都会有一大堆的输出结果在命令行中,看起来很乱,而在prod
环境中我们可以设置为normal
performance
性能提示相关,如果超出了设置的大小,则会打印对应的提示信息,这个我们可以只配置在webpack.prod.conf.js
中
完整配置
好了,现在我们来看一下添加这些配置项以后各个文件的内容吧,首先是webpack.dev.conf.js
const merge = require('webpack-merge')
const webpack = require('webpack')
const config = require('./config')
const baseWebpackConfig = require('./webpack.base.conf')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
mode: 'development',
module: {},
stats: 'errors-only',
devtool: config.dev.devtool,
devServer: {
// http://[devServer.host]:[devServer.port]/[output.publicPath]/[output.filename] 进行访问
historyApiFallback: true,
hot: true,
client: {
overlay: config.dev.errorOverlay ? { warnings: false, errors: true } : false,
logging: 'none',
progress: true
},
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
proxy: config.dev.proxyTable
},
plugins: [new webpack.HotModuleReplacementPlugin()]
})
module.exports = devWebpackConfig
复制代码
然后是webpack.prod.conf.js
文件
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const { resolve } = require('./utils')
const config = require('./config')
const webpackConfig = merge(baseWebpackConfig, {
mode: 'production',
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: resolve('dist'),
filename: 'js/[name].[chunkhash].js',
publicPath: './',
clean: true
},
stats: 'normal',
cache: {//...},
performance: {
maxEntrypointSize: 5 * 1024 * 1024,
maxAssetSize: 3 * 1024 * 1024,
hints: 'warning'
},
optimization: {//...},
plugins: [//...]
})
module.exports = webpackConfig
复制代码
功能添加
接下来,我们参考vue-cli
提供的功能,进一步完善我们的配置,首先是针对开发环境
portfinder
如果配置的端口号已经被占用,则自动+1,这个功能需要用到portfinder
,具体使用我们会结合下一个插件一起讲
yarn add portfinder -D
复制代码
FriendlyErrorsPlugin
自定义打包成功时的提示信息,感兴趣的同学可以在每次dev-server启动成功后打印出一个皮卡丘
yarn add friendly-errors-webpack-plugin -D
复制代码
这两个插件都是用在webpack.dev.conf.js
中,具体代码如下:
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
// ...
const devWebpackConfig = merge(baseWebpackConfig,{...})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(
new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [
`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`
],
notes: []
},
clearConsole: true
})
)
resolve(devWebpackConfig)
}
})
})
复制代码
文件拷贝
将public文件中的文件拷贝到dist文件下
yarn add copy-webpack-plugin -D
复制代码
这个功能只在打包的时候用到,所以我们在webpack.prod.conf.js
中添加如下代码
const CopyWebpackPlugin = require('copy-webpack-plugin')
const webpackConfig = merge(baseWebpackConfig, {
//...
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: resolve('public'),
to: './',
globOptions: {
dot: true,
gitignore: true
}
}
]
})
//...
]
})
复制代码
gzip/bundleAnalyzerReport
文件是否开启gzip压缩和是否生成打包报告,同样的只在打包的时候才用到
首先添加依赖
yarn add compression-webpack-plugin webpack-bundle-analyzer -D
复制代码
然后我们在webpack.prod.conf.js
中添加如下代码
const config = require('./config')
const webpackConfig = merge(baseWebpackConfig,{//...})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp('\\.(' + config.build.productionGzipExtensions.join('|') + ')$'),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
复制代码
自动引入环境变量
在vue-cli中,我们可以在项目根目录中放置下列文件来指定环境变量
.env # 在所有的环境中被载入
.env.local # 在所有的环境中被载入,但会被 git 忽略
.env.[mode] # 只在指定的模式中被载入
.env.[mode].local # 只在指定的模式中被载入,但会被 git 忽略
复制代码
这个功能主要是通过dotenv
这个包实现的,接下来我们也在项目中添加这个包
yarn add dotenv fs-extra -D
复制代码
在页面中添加loadEnvDefine
方法
const fs = require('fs-extra')
const path = require('path')
exports.loadEnvDefine = (mode) => {
const envDefine = {}
if (fs.existsSync(`.env.${mode}`)) {
require('dotenv').config({ path: `.env.${mode}` })
const prefixRE = /^VUE_APP_/
const envDefine = {}
for (const key in process.env) {
if (key == 'NODE_ENV' || key == 'BASE_URL' || prefixRE.test(key)) {
envDefine[key] = JSON.stringify(process.env[key])
}
}
}
return envDefine
}
复制代码
在webpack.base.conf.js
文件中引入这个方法,并通过DefinePlugin
注册到全局中
const { loadEnvDefine } = require('./utils')
const webpack = require('webpack')
module.exports = {
//...
plugins: [
// ....,
new webpack.DefinePlugin({
'process.env': { ...loadEnvDefine(process.env.NODE_ENV) }
})]
}
复制代码
总结
好了,我们的项目到这里可以说是搭建完成了,基本实现了vue-cli提供的大部分功能,如果大家有什么疑问或者建议,欢迎大家留言交流~