vue-cli搭建webpack4项目

    科技2024-01-18  99

    先前开发了一个中大型的项目,修改下代码热更新30秒,项目启动4分钟,打包就更可怕了一打一上午。现在想通过webpack4好好优化一下,先弄个测试项目整整。

    走起!初始化vue-cli项目

    初始化的package.json文件

    { "name": "create-dome-linwenjie", "version": "1.0.0", "description": "A Vue.js project", "author": "HandsomeLin <597167890@qq.com>", "private": true, "scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "build": "node build/build.js" }, "dependencies": { "vue": "^2.5.2" }, "devDependencies": { "autoprefixer": "^7.1.2", "babel-core": "^6.22.1", "babel-helper-vue-jsx-merge-props": "^2.0.3", "babel-loader": "^7.1.1", "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-runtime": "^6.22.0", "babel-plugin-transform-vue-jsx": "^3.5.0", "babel-preset-env": "^1.3.2", "babel-preset-stage-2": "^6.22.0", "chalk": "^2.0.1", "copy-webpack-plugin": "^4.0.1", "css-loader": "^0.28.0", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^1.1.4", "friendly-errors-webpack-plugin": "^1.6.1", "html-webpack-plugin": "^2.30.1", "node-notifier": "^5.1.2", "optimize-css-assets-webpack-plugin": "^3.2.0", "ora": "^1.2.0", "portfinder": "^1.0.13", "postcss-import": "^11.0.0", "postcss-loader": "^2.0.8", "postcss-url": "^7.2.1", "rimraf": "^2.6.0", "semver": "^5.3.0", "shelljs": "^0.7.6", "uglifyjs-webpack-plugin": "^1.1.1", "url-loader": "^0.5.8", "vue-loader": "^13.3.0", "vue-style-loader": "^3.0.1", "vue-template-compiler": "^2.5.2", "webpack": "^3.6.0", "webpack-bundle-analyzer": "^2.9.0", "webpack-dev-server": "^2.9.1", "webpack-merge": "^4.1.0" }, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" }, "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] }

    开始升级webpack4

    修改package.json文件为下列版本,先删除原先版本(随后 npm i 下载新版本,接着npm run dev启动):

    "webpack": "^4.5.0", "webpack-dev-server": "^3.1.4",

    在package.json中添加 “webpack-cli”依赖 (随后 npm i 下载新版本,接着npm run dev启动)

    "webpack-cli":"^3.1.0",

    修改package.json文件为下列版本,先删除原先版本(随后 npm i 下载新版本,接着npm run dev启动):

    "html-webpack-plugin": "^3.2.0",

    修改package.json文件为下列版本,先删除原先版本(随后 npm i 下载新版本,接着npm run dev启动):

    "eslint-loader": "2.0.0",

    修改package.json文件为下列版本,先删除原先版本(随后 npm i 下载新版本,接着npm run dev启动):

    "vue-loader": "^15.3.0",

    由于webpack4 版本依赖VueLoaderPlugin 插件,所以还需要去配置webpack.base.conf.js文件:

    // 引入插件包 const VueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = { .... plugins: [ new VueLoaderPlugin() ], }

    接着在为开发配置文件(webpack.dev.conf.js)和生产配置文件(webpack.prod.conf.js)分别配置mode属性:

    mode:'development', module: { ... }, mode:'production', module: { ... },

    继续npm run dev启动项目 由于在webpack4之后,不允许混用 exports和import。修改webpack.base.conf.js文件:

    { test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test')] },

    到这里开发环境项目正常运行!接下来配置生产环境执行 npm run build 进行打包。 接下的配置应该是从V3升级到V4的代码修改过程中最为复杂的一部分。

    从webpack4开始官方移除了CommonsChunkPlugin插件,改用了optimization属性进行更加灵活的配置,所以要进行替换。将“extract-text-webpack-plugin” 使用“mini-css-extract-plugin” 替换,这两个插件是用来提取单独打包css文件,webpack4需要使用后者。(记得下载依赖 “mini-css-extract-plugin”: “^0.12.0”)

    build/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 ExtractTextPlugin = require('extract-text-webpack-plugin') const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin') //webpack4 用该插件提取单独打包css文件 替代原来的 “extract-text-webpack-plugin” const env = require('../config/prod.env') 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].[chunkhash].js'), chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') }, // 使用该配置替代下面的CommonsChunkPlugin插件 optimization: { minimizer: [ new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: true }) ], splitChunks: { cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, chunks: 'initial', name: 'vendors', }, 'async-vendors': { test: /[\\/]node_modules[\\/]/, minChunks: 2, chunks: 'async', name: 'async-vendors' } } }, runtimeChunk: { name: 'runtime' } }, plugins: [ // http://vuejs.github.io/vue-loader/en/workflow/production.html new webpack.DefinePlugin({ 'process.env': env }), // new UglifyJsPlugin({ // uglifyOptions: { // compress: { // warnings: false // } // }, // sourceMap: config.build.productionSourceMap, // parallel: true // }), // extract css into its own file // new ExtractTextPlugin({ // filename: utils.assetsPath('css/[name].[contenthash].css'), // // Setting the following option to `false` will not extract CSS from codesplit chunks. // // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. // // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, // // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 // allChunks: true, // }), new MiniCssExtractPlugin({ filename: utils.assetsPath('css/[name].[contenthash].css'), allChunks: true, }), // Compress extracted CSS. We are using this plugin so that possible // duplicated CSS from different components can be deduped. new OptimizeCSSPlugin({ cssProcessorOptions: config.build.productionSourceMap ? { safe: true, map: { inline: false } } : { safe: true } }), // generate dist index.html with correct asset hash for caching. // you can customize output by editing /index.html // see https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ filename: config.build.index, template: 'index.html', inject: true, minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true // more options: // https://github.com/kangax/html-minifier#options-quick-reference }, // necessary to consistently work with multiple chunks via CommonsChunkPlugin chunksSortMode: 'dependency' }), // keep module.id stable when vendor modules does not change new webpack.HashedModuleIdsPlugin(), // enable scope hoisting // new webpack.optimize.ModuleConcatenationPlugin(), // split vendor js into its own file // new webpack.optimize.CommonsChunkPlugin({ // name: 'vendor', // minChunks (module) { // // any required modules inside node_modules are extracted to vendor // return ( // module.resource && // /\.js$/.test(module.resource) && // module.resource.indexOf( // path.join(__dirname, '../node_modules') // ) === 0 // ) // } // }), // extract webpack runtime and module manifest to its own file in order to // prevent vendor hash from being updated whenever app bundle is updated // new webpack.optimize.CommonsChunkPlugin({ // name: 'manifest', // minChunks: Infinity // }), // This instance extracts shared chunks from code splitted chunks and bundles them // in a separate chunk, similar to the vendor chunk // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk // new webpack.optimize.CommonsChunkPlugin({ // name: 'app', // async: 'vendor-async', // children: true, // minChunks: 3 // }), // copy custom static assets new CopyWebpackPlugin([{ from: path.resolve(__dirname, '../static'), to: config.build.assetsSubDirectory, ignore: ['.*'] }]) ] }) 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

    build/utils.js文件修改

    'use strict' const path = require('path') const config = require('../config') const ExtractTextPlugin = require('extract-text-webpack-plugin') const packageConfig = require('../package.json') const MiniCssExtractPlugin = require('mini-css-extract-plugin') 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 ExtractTextPlugin.extract({ // use: loaders, // fallback: 'vue-style-loader' // }) // } else { // return ['vue-style-loader'].concat(loaders) // } 升级 webpack4, 由 ExtractTextPlugin 改用 MiniCssExtractPlugin return [ options.extract ? MiniCssExtractPlugin.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') }) } }

    修改完之后对项目进行打包(npm run build)成功!

    参考质料

    升级指南

    以上就是我对升级webpack4的理解,如果文章由于我学识浅薄,导致您发现有严重谬误的地方,请一定在评论中指出,我会在第一时间修正我的文章,以避免误人子弟。

    Processed: 0.021, SQL: 8