背景

19年新建的vue项目,使用的是webpack3,随着项目的积累,组件的增多导致本地构建,线上打包等操作速度极慢,非常影响开发效率和部署效率,基于此问题,本次对webpack及相关插件进行了优化和升级。本博文分为2篇,第 1 篇 会直接附上可运行的代码(去除了一些业务代码配置),直接粘贴复制即可使用(注意是基于vue2.0项目原配置基础上的修改哦,在网上找了一堆都是升级过程的各种坑说明,不如直接粘贴复制运行来的爽丫~~~),第 2 篇也会对相关的修改和遇到的坑进行描述说明。

升级效果

1、本地构建

第一次构建 5分钟 缩短至 1.5分钟左右, 构建时间提升近 4 倍

更新构建 由 5-10s 缩短至 1-5s ,构建提升 2 倍

2、线上打包

执行npm run build 由10-15分钟 缩短至 3-5分钟,构建时间提升近4倍

升级过程

1. 更新webpack依赖
yarn upgrade webpack@5.37.0
yarn add webpack-dev-server webpack-cli -D

更新其他相关的组件,这里不需要一个个找了,可以使用npm-check-updates一键升级所需的组件,不再赘述怎么用的了,百度一下,你就知道,实在不会就一个个install吧~

2. package.json启动命令修改
  "scripts": {
"dev": "npx webpack serve --config build/webpack.dev.conf.js --color --progress",
"build": "node build/build.js",
"dll": "npx webpack --config build/webpack.dll.conf.js",
"start": "npm run dev"
}
3、webpack.base.conf.js配置修改
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const webpack = require('webpack')
const vueLoaderConfig = require('./vue-loader.conf')
const { VueLoaderPlugin } = require('vue-loader'); function resolve (dir) {
return path.join(__dirname, '..', dir)
} module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.ts'
},
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', '.ts'],
alias: {
vue$: 'vue/dist/vue.esm.js',
'@': resolve('src'),
pages: resolve('src/pages')
}
},
module: {
rules: [
{
test: /\.vue$/,
use: {
loader: 'vue-loader'
}
},
{
test: /\.tsx?$/,
exclude: resolve('node_modules'),
use: [
{
loader: 'babel-loader'
},
{
loader: "ts-loader",
options: { appendTsxSuffixTo: [/\.vue$/], transpileOnly: true }
}
]
},
{
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]')
}
}
]
},
node: {
global: false
},
plugins: [
new VueLoaderPlugin(),
new webpack.ProvidePlugin({
jQuery: 'jquery',
$: 'jquery'
}),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: path.resolve(__dirname, './vendors.manifest.json')
})
]
}
4、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 })
},
devtool: config.dev.devtool,
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false,
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,
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: 'body',
scriptLoading: 'blocking',
minify: {
removeComments: true
}
}),
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 {
process.env.PORT = port
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)
}
})
})
5、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 OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
const TerserWebpackPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const env = require('../config/prod.env') const webpackConfig = merge(baseWebpackConfig, {
mode: "production",
module: {
rules: utils.styleLoaders({
sourceMap: false,
extract: true,
usePostCSS: true
})
},
devtool: config.build.devtool,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].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: [
new webpack.DefinePlugin({
'process.env': env
}),
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: true
})
)
} if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
} module.exports = webpackConfig
6、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,
}
].concat(loaders)
} else {
return [
{
loader: '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]; // console.log("css-loader", loader)
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')
})
}
}

转载请说明来处 黑玛鱼的前端博客

老vue项目webpack3升级到webpack5全过程记录(一)的更多相关文章

  1. Eclipse 导入项目与 svn 插件关联全过程记录

    文章摘自:http://www.cnblogs.com/xmmcn/archive/2013/03/01/2938365.html 感谢博友分享! Eclipse 导入项目与 svn 插件关联全过程记 ...

  2. 在vue项目中的axios使用配置记录

    默认vue项目中已经安装axios,基于element-ui开发,主要记录配置的相关. axiosConfig.js import Vue from 'vue' import axios from ' ...

  3. vue项目node升级后,node-saas报错解决办法

    ERROR in ./node_modules/_extract-text-webpack-plugin@3.0.2@extract-text-webpack-plugin/dist/loader.j ...

  4. 如何快速把 Vue 项目升级到 webpack3

    由于 webpack3升级后,新增了 Scope Hositing(作用域提升) 功能,据说是对 js的性能提升很大.因此,我们做了一个测试对比,就是 webpack3和 webpack1/2 的性能 ...

  5. Vue项目搭建完整剖析全过程

    Vue项目搭建完整剖析全过程 项目源码地址:https://github.com/ballyalex 有帮助的话就加个星星呗~!  项目技术栈:vue+webpack+bower+sass+axios ...

  6. prettier包升级后vue项目运行报错

    今天用vue-cli新建vue项目的时候,发现项目怎么都跑不起来. 最后通过与以前项目作比较,发现prettier这个依赖的版本从原来的1.12.0升级成了1.13.1.我也不太清楚为什么升级后项目跑 ...

  7. 简单vue项目脚手架(vue+webpack2.0+vuex+vue-router)

    github地址 使用技术栈 webpack(^2.6.1) webpack-dev-server(^2.4.5) vue(^2.3.3) vuex(^2.3.1) vue-router(^2.5.3 ...

  8. 原有vue项目接入typescript

    原有vue项目接入typescript 为什么要接入typescript javascript由于自身的弱类型,使用起来非常灵活. 这也就为大型项目.多人协作开发埋下了很多隐患.如果是自己的私有业务倒 ...

  9. element-ui和npm、webpack、vue-cli搭建Vue项目

    一.element-ui的简单使用 1.安装 1. npm 安装 推荐使用 npm 的方式安装,它能更好地和 webpack 打包工具配合使用. npm i element-ui -S 2. CDN ...

随机推荐

  1. Git本地仓库基本操作-1

    code[class*="language-"], pre[class*="language-"] { color: rgba(51, 51, 51, 1); ...

  2. [树形DP]没有上司的晚会

    没 有 上 司 的 晚 会 没有上司的晚会 没有上司的晚会 题目描述 Ural大学有N个职员,编号为1~N.他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.每个职 ...

  3. Recoil 中多级数据联动及数据重置的合理做法

    前情回顾 书接上回,前面引出了在数据存在级联的情况下,各下拉框之间的默认值及值变化的处理.简单回顾一下: 场景是: 地域下拉决定可选的可用区 默认选中第一个地域,通过设置 atom 的 default ...

  4. Ubuntu16.04下安装virtualbox,配置及卸载

    我是通过添加源的方式安装 将下边的命令添加到/etc/apt/source.list中 deb https://download.virtualbox.org/virtualbox/debian xe ...

  5. linux系统调用号查询(pwn)

    做pwn题时遇到程序使用了64位系统调用号:59和15,这里做一下记录 在线查询链接:https://syscalls.w3challs.com/ 分为32位和64位,链接中还有arm.mips等架构 ...

  6. kubernetes 查看cpu,内存使用情况

    kubectl top pod --all-namespaces kubectl top pod -n kubeflow

  7. Django+Vue+Docker搭建接口测试平台实战

    一. 开头说两句 大家好,我叫林宗霖,是一位测试工程师,也是全栈测开训练营中的一名学员. 在跟着训练营学习完Docker容器技术系列的课程后,理所应当需要通过实操来进行熟悉巩固.正好接口自动化测试平台 ...

  8. 鸿蒙HI3516-驱动开发(1.1-LTS)

    代码在:https://gitee.com/kwydm/open-harmony-taurus 目录大致结构 1.驱动开发创建目录://vendor/huawei/hdf/LED/src 新建Make ...

  9. Pandas——Series and DataFrane

    数据科学--pandas库 pandas中有两个主要的数据结构,一个是Series,另一个是DataFrame.通过这两类数据,可以下载数据.可视化数据.和分析数据. Pandas安装:pip ins ...

  10. php中var关键字用法

    见很多朋友说在php中定义变量用不用var都没关系,其实不然. 看看例子,如果我这样使用var: 1 var $a=123; 2 echo $a; 3 //那么程序会提示语法错误,要去掉var这个变量 ...