vuecli2.x webpack3.x升级webpack5.37.0
Posted Samsara315
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vuecli2.x webpack3.x升级webpack5.37.0相关的知识,希望对你有一定的参考价值。
随着项目的页面越来越多体积越来越大,dev构建速度和pro打包速度越来越慢,然后就抽时间对项目进行了webpack升级来提升一下速度
升级过程中遇到了很多的坑,基本都是plugin和loader升级后的一些用法问题,花了一个晚上和一个上午时间,过程很痛苦,但是看到
速度的大幅度提示,还是很开心的
先上图看一下对比效果
webpack3 dev构建
webpack3 pro打包
webpack5 dev构建 提升60%
webpack5 pro 构建 提升23%
看的处理效果还是很不错的
1.首先是对webpack进行升级,升级后的版本如图
升级后一些用法发生了改变
webpack-merge的变化
dev启动命令变化
2.由于wepback的升级造成了其他一些插件或者loader的不能正常使用,索性使用yarn upgrade-interactive --latest升级了所有的依赖包
3.升级后报错babel-core6.x的版本需要使用babel-loader7的版本然后重新安装yarn add -D babel-loader@7
4.安装mini-css-extract-plugin替换extract-text-webpack-plugin
webpack.base.config.js
\'use strict\'
const path = require(\'path\')
const utils = require(\'./utils\')
const config = require(\'../config\')
const { VueLoaderPlugin } = require(\'vue-loader\')
function resolve(dir) {
return path.join(__dirname, \'..\', dir)
}
module.exports = {
devtool:\'eval-source-map\',
context: path.resolve(__dirname, \'../\'),
entry: {
app: \'./src/main.js\'
},
output: {
path: config.build.assetsRoot,
filename: \'[name].js\',
publicPath: process.env.NODE_ENV === \'production\' ?
config.build.assetsPublicPath : config.dev.assetsPublicPath
},
resolve: {
extensions: [\'.js\', \'.vue\', \'.json\'],
alias: {
\'vue$\': \'vue/dist/vue.esm.js\',
\'@\': resolve(\'src\'),
}
},
module: {
rules: [{
test: /\\.vue$/,
use: {
loader: \'vue-loader\'
}
},
{
test: /\\.js$/,
use: {
loader: \'babel-loader\'
},
exclude: resolve(\'node_modules\'),
include: resolve(\'src\')
},
{
test: /\\.(png|jpe?g|gif|svg)(\\?.*)?$/,
type: \'asset\',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 // 10kb
}
},
generator: {
filename: utils.assetsPath(\'img/[name].[hash:7].[ext]\')
}
},
{
test: /\\.(mp4|webm|ogg|mp3|wav|flac|aac)(\\?.*)?$/,
loader: \'url-loader\',
options: {
limit: 10000,
name: utils.assetsPath(\'media/[name].[hash:7].[ext]\')
}
},
{
test: /\\.(woff2?|eot|ttf|otf)(\\?.*)?$/,
loader: \'url-loader\',
options: {
limit: 10000,
name: utils.assetsPath(\'fonts/[name].[hash:7].[ext]\'),
publicPath: \'../../\'
}
}]
},
node: {
global: false
},
plugins: [
new VueLoaderPlugin()
]
}
utils.js
\'use strict\'
const path = require(\'path\')
const config = require(\'../config\')
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const packageConfig = require(\'../package.json\')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === \'production\'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
const cssLoader = {
loader: \'css-loader\',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: \'postcss-loader\',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders(loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + \'-loader\',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: \'../../\' //修改路径处理图片路径错误
}
}
].concat(loaders)
} else {
return [
{
loader: \'vue-style-loader\'
}
].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders(\'less\'),
// sass: generateLoaders(\'sass\', { indentedSyntax: true }),
// scss: generateLoaders(\'sass\'),
// stylus: generateLoaders(\'stylus\'),
// styl: generateLoaders(\'stylus\')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp(\'\\\\.\' + extension + \'$\'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require(\'node-notifier\')
return (severity, errors) => {
if (severity !== \'error\') return
const error = errors[0]
const filename = error.file && error.file.split(\'!\').pop()
notifier.notify({
title: packageConfig.name,
message: severity + \': \' + error.name,
subtitle: filename || \'\',
icon: path.join(__dirname, \'logo.png\')
})
}
}
webpack.dev.conf.js
\'use strict\'
const utils = require(\'./utils\')
const webpack = require(\'webpack\')
const config = require(\'../config\')
const { merge } = require(\'webpack-merge\')
const path = require(\'path\')
const baseWebpackConfig = require(\'./webpack.base.conf\')
const CopyWebpackPlugin = require(\'copy-webpack-plugin\')
const HtmlWebpackPlugin = require(\'html-webpack-plugin\')
const FriendlyErrorsPlugin = require(\'friendly-errors-webpack-plugin\')
const portfinder = require(\'portfinder\')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
mode: \'development\',
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: \'warning\',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, \'index.html\') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay ? { warnings: false, errors: true } : false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
\'process.env\': require(\'../config/dev.env\'),
BASEURL: \'"//test.com"\',
}),
new webpack.HotModuleReplacementPlugin(),
// new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
// new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: \'index.html\',
template: \'index.html\',
inject: true,
chunkSortMode: \'auto\'
}),
// copy custom static assets
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, \'../static\'),
to: config.dev.assetsSubDirectory,
globOptions: {
dot: true,
gitignore: true,
ignore: [\'.*\'],
}
},
]
})
]
})
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}`],
},
onErrors: config.dev.notifyOnErrors ?
utils.createNotifierCallback() : undefined
}))
resolve(devWebpackConfig)
}
})
})
webpack.prod.conf.js
\'use strict\'
const path = require(\'path\')
const utils = require(\'./utils\')
const webpack = require(\'webpack\')
const config = require(\'../config\')
const { merge } = require(\'webpack-merge\')
const baseWebpackConfig = require(\'./webpack.base.conf\')
const CopyWebpackPlugin = require(\'copy-webpack-plugin\')
const HtmlWebpackPlugin = require(\'html-webpack-plugin\')
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const TerserWebpackPlugin = require(\'terser-webpack-plugin\')
const OptimizeCSSPlugin = require(\'optimize-css-assets-webpack-plugin\')
const env = require(\'../config/prod.env\')
let envOptions = {}
if (process.env.BUILD_ENV === "production") {
envOptions = {
\'BASEURL\': \'"//test.com"\',
}
} else {
envOptions = {
\'BASEURL\': \'"//test.com"\',
}
}
const webpackConfig = merge(baseWebpackConfig, {
mode: \'production\',
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath(\'js/[name].[hash:7].js\'),
chunkFilename: utils.assetsPath(\'js/[name].[hash:7].js\'),
clean: true
},
optimization: {
minimize: true,
minimizer: [
new TerserWebpackPlugin(),
new OptimizeCSSPlugin(),
],
runtimeChunk: { name: \'runtime\' },
concatenateModules: true,
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\\\/]node_modules[\\\\/]/,
name: \'vendor\',
chunks: \'all\',
priority: -10
},
\'async-vendors\': {
test: /[\\\\/]node_modules[\\\\/]/,
minChunks: 2,
chunks: \'async\',
name: \'async-vendors\'
}
},
},
moduleIds: \'deterministic\'
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
\'process.env\': env,
...envOptions,
}),
new MiniCssExtractPlugin({
filename: utils.assetsPath(\'css/[name].[contenthash].css\'),
chunkFilename: utils.assetsPath(\'css/[name].[contenthash].css\')
}),
new HtmlWebpackPlugin({
filename: config.build.index,
template: \'index.html\',
inject: true,
scriptLoading: \'blocking\',
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: \'auto\'
}),
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, \'../static\'),
to: config.build.assetsSubDirectory,
globOptions: {
dot: true,
gitignore: true,
ignore: [\'.*\'],
}
},
]
})
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require(\'compression-webpack-plugin\');
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
filename: \'[path][base].gz[query]\',
algorithm: \'gzip\',
test: /\\.(js|css|json|txt|html|ico|svg)(\\?.*)?$/i,
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: false//保留源文件
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require(\'webpack-bundle-analyzer\').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
以上是关于vuecli2.x webpack3.x升级webpack5.37.0的主要内容,如果未能解决你的问题,请参考以下文章