Integrated Webpack5

Migrate documents: webpack.js.org/migrate/5

Migration: webpack.js.org/migrate/5/#…

Before WebPack 4, you didn’t need to install Webpack-CLI. After webpack4, it separated Webpack and Webpack-CLI, requiring a Webpack-CLI installation

  • A a pit

Github.com/webpack/web… You need to wait for the webpack-dev-server update to use the plugin, otherwise WebPack Serve is not compatible with the plugin

  • A second pit

    var { merge } = require('webpack-merge')
    Copy the code
  • A three

    Configure the migration

    - new webpack. NamedModulesPlugin () + optimization: {moduleIds: 'named', / * * NamedModulesPlugin module migration /}Copy the code
    - new webpack. NoEmitOnErrorsPlugin () + optimization: {emitOnErrors: true / * * /} NoEmitOnErrorsPlugin module migrationCopy the code
  • Pit is a four

    Upgrade ** html-webpack-plugin** plugin to version 5 compatible with WebPack 5

    npm i --save-dev html-webpack-plugin@next
    Copy the code

Webpck5 document

Since the webpack-dev-server was updated to 4, many configurations have been problematic

  • webpack-merge:webpackConfigure merge module
  • webpack: package tool, also become a build tool, use watch configuration can not usewebpack-dev-middlewareThe plug-in
  • webpack-cli: Command line tool
  • webpack-dev-server: hot loading [a small Express server officially provided by Webpack]
  • Time 2021 1/1/16 Upgrade Webpack-dev-server 3.11.0 is incompatible with WebPack5

    NPM [email protected] - I DCopy the code

    Major change

    DevServer remove the log, logLevel, logTime noInfo, quiet, reporter and warn option / / webpack.docschina.org/configurati… Remove the -quiet

    NPM [email protected] - I DCopy the code
    NPM [email protected] - I DCopy the code
    NPM [email protected] - I DCopy the code
- npm i webpack webpack-cli webpack-dev-server webpack-merge -D
+ NPM I [email protected] [email protected] [email protected] [email protected] -d
Copy the code

Rules configuration

Configuration writing specificationeslint

  • eslint-friendly-formatter: you can makeeslintError message is displayed on the terminal
  • eslint eslint-loader:js vuefileeslintValidation rules
npm i eslint eslint-loader eslint-friendly-formatter -D
Copy the code

Webpack configuration

{test: / \. (js | vue) $/, loader: 'eslint - loader, enforce:' pre '/ * front, code parsing a first eslint * / include: [[resolve(' SRC '), resolve('test')]],/* SRC test */ options: {formatter: Require ('eslint-friendly-formatter')/* Can make ESLint error messages appear on terminals */}}Copy the code

Parsing advanced syntaxbabel-loader

  • Babel-loader: In order to parse Es6 and other advanced syntax, we introduced babel-loader parsing

  • Babel /core: The core of Babel

  • Babel /preset-env: A set of plugins, including es2015, ES2016, ES2017, the latest syntax-conversion plugins we used in Babel6

    npm i babel-loader @babel/core @babel/preset-env -D
    Copy the code

    Webpack configuration

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

    .babelrc

    {
        "presets": [
          "@babel/preset-env"
        ]
    }
    Copy the code

The plugin plug-in

  • html-webpack-plugin

    It will automatically generate an HTML file for you

    npm i html-webpack-plugin -D
    Copy the code
  • extract-text-webpack-plugin

    Sometimes we need the extract-text-webpack-plugin when we don’t want to type styles into scripts, but want to isolate CSS and then link CSS to the page

    NPM [email protected] - I DCopy the code
    • CSS analytical

      npm i css-loader postcss-loader style-loader -D
      Copy the code
    • CSS Add browser prefix, compress CSS, postCSS-loader under many plug-ins

  • friendly-errors-webpack-plugin

    Friendly error prompt plug-in that identifies certain categories of Webpack errors and cleans, aggregates and prioritizes them to provide a better developer experience

    NPM [email protected] - I DCopy the code
  • node-notifier

    System-level message alerts

    npm install --save node-notifier
    Copy the code
  • terser-webpack-plugin

    If you are using WebPack V5 or above, you do not need to install this plugin. Webpack V5 comes with the latest Terser-webpack-plugin

    npm install terser-webpack-plugin --save-dev
    Copy the code
  • cache-loader

    The cache-loader is added before the loader that has high performance overhead to save the result to disk to reduce compilation time

    npm install cache-loader --save-dev
    Copy the code

Parsing various styles

  • css-loader: parsing.cssfile
  • postcss-loader: parsingcssThe prefix
    • postcss-importThe version is too high and needs to be reduced first
    • postcss-urlThe version is too high and needs to be reduced first
    • autoprefixerThe version is too high and needs to be reduced first
  • style-loaderparsingvueIn the filestyle Not good to use vue-style-loader
npm i css-loader postcss-loader style-loader -D
Copy the code

Optimize the compilation

Some performance overhead added front loader cache – loader, the results are cached disk to reduce compilation time www.cnblogs.com/zhonglinfen…

Install vue3

Stackoverflow.com/questions/6…

npm install vue@next vue-loader@next
Copy the code

@ vue/alternative vue – the template – the compiler compiler – SFC

@vue/ Compiler – The SFC must be consistent with the VUE version

Configuration summary map

Configuration links are basically pit records

Project demo by yourself [gitee.com/lukangfeng/…]

build/utils.js

/* const PKG = require('.. /package.json') /* The main purpose of this plugin is to extract CSS styles and prevent the loading of page styles by packing styles in JS */ const ExtractTextPlugin = / / exports.getassetPath = function require('extract-text-webpack-plugin') const path = require('path') /* exports.getassetPath = function (filePath, options = {}) { return options.assetsDir ? path.posix.join(options.assetsDir, filePath) : FilePath} analytical CSS / * * / exports. CssLoaders = function (options) {options = options | | {} / * parsing. CSS file * / const cssLoader = { loader: 'css-loader', options: { // https://github.com/vuejs/vue-style-loader/issues/50 // https://github.com/vuejs/vue-style-loader#differences-from-style-loader // esModule: False, // Default to true vue-style-loader is an encapsulation of style-loader -- use style-loader or esModule: False // tips use style-loader instead of vue-style-loader sourceMap: Options. sourceMap}} /* Parsing prefix CSS */ const postcssLoader = {loader: 'postCSs-loader ', options: {sourceMap: Options. sourceMap}} // Generate the loader string used to extract the text plug-in const generateLoaders = (loader, LoaderOptions) => {/* Whether to use parsing prefix */ const loaders = options.usePostCSS? [cssLoader, postcssLoader] : [cssLoader] if (loader) {/* Add loaders.push({loader: Loader + '-loader', /* options: object. assign({}, loaderOptions, {sourceMap: Options. sourceMap})})} // When this option is specified CSS is extracted to a separate file // (during production build) if (options.extract) {return ExtractTextPlugin.extract({ use: loaders, fallback: 'style-loader' // use style-loader instead of vue-style-loader https://github.com/vuejs/vue-style-loader#differences-from-style-loader }) } else { return ['style-loader']. Concat (loaders) // Replace vue-style-loader with style-loader https://github.com/vuejs/vue-style-loader#differences-from-style-loader } } // https://vue-loader.vuejs.org/en/configurations/extract-css.html / * only for CSS extraction production application, so that during the period of development for CSS hot reload * / return {CSS: generateLoaders(), postcss: generateLoaders(), less: generateLoaders('less'), sass: generateLoaders('sass', { indentedSyntax: true }), scss: generateLoaders('sass'), stylus: GenerateLoaders ('stylus')}} // An exports.styleLoaders = function (options) {const output = [] /* Preprocessing CSS type has stylus SCSS sass postcss CSS */ const loaders = exports.cssloaders (options) /* To carry all types */ for (const extension in loaders) { const loader = loaders[extension] output.push({ test: new RegExp('\\.' + extension + '$'), use: Loader}}) return the output} / * error correction * / exports in createNotifierCallback = function () {/ * * system level news/const notifier = Return (severity, errors) => {return */ if (severity! == 'error') {return} /* Get first error */ const error = errors[0] const filename = error.file && error.file.split('! ').pop() notifier. Notify ({title: pkg.name /* project name */, message: severity + ': '+ error. Name /* level + error message */, subtitle: Filename | | '/ * * / error files, icon: path. Join (__dirname,' logo. PNG ') logo / * * /}}}Copy the code

build/webpack.base.conf.js

const path = require('path') const config = require('.. /config') const utils = require('./utils') const {VueLoaderPlugin} = require('vue-loader') /* resolve */ const resolve = (dir) => { return path.join(__dirname, '.. ', dir) } const createLintingRule = () => ({ test: /\.(js|vue)$/, loader: 'eslint-loader', enforce: 'pre', include: [resolve('src'), resolve('test')], options: { formatter: require('eslint-friendly-formatter'), emitWarning: ! Config. Dev. ShowEslintErrorsInOverlay}}) / / now the mode of basic it is inside the package statement execution Settings -- mode development module. Exports = {context: path.resolve(__dirname, '.. /'), output: {path: config.build.assetsRoot /* Compile to what file */, publicPath: process.env.node_env === 'production'? config.build.assetsPublicPath : config.dev.assetsPublicPath, filename: '[name].js', chunkFilename: '[name].js'}, /* Set how the module will be resolved */ resolve: {/* Automatically resolve the identified extension. ['. Js', 'vue', 'json'], / * alias * / alias: {' @ ': resolve (' SRC'), vue $: 'vue/dist/vue. Esm - bundler. Js'}}, plugins: [new VueLoaderPlugin()], target: 'web', // webPack5.x Whether need open test... [/ / eslint configuration (config. Dev. UseEslint? [createLintingRule ()] : []), {test: / \. (js | JSX) $/, use: ['cache-loader', 'babel-loader'], exclude: /node_modules/, include: [resolve('src'), resolve('test')] }, // https://stackoverflow.com/questions/64868632/vuejs-3-problem-with-vue-template-compiler { test: /\.vue$/, use: [ 'cache-loader', { loader: 'vue-loader', options: { compilerOptions: { preserveWhitespace: False // do not want Spaces between elements}, babelParserPlugins: [ 'jsx', 'classProperties', 'decorators-legacy' ] } } ] }, {/ / https://webpack.docschina.org/guides/asset-modules/ resource module test: / \. (PNG | jpe? G | | GIF SVG) (\? *)? $/, type: 'asset', parser: { dataUrlCondition: { maxSize: 4 * 1024 * 1024 // 4M---- less than 4M baser64 if greater than 4M the module file will be generated to the output target directory}}, generator: {filename: Utils. GetAssetPath (' img / [name] [5] hash: [ext] ') / / (ext) represents the file suffix}}, {test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, type: 'asset', parser: { dataUrlCondition: { maxSize: 2 * 1024 * 1024 // 4M } }, generator: { filename: utils.getAssetPath('media/[name].[hash:5][ext]') } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, type: 'asset', parser: { dataUrlCondition: { maxSize: 2 * 1024 * 1024 // 4M } }, generator: { filename: utils.getAssetPath('fonts/[name].[hash:5][ext]') } } ] } }Copy the code

build/webpack.dev.conf.js

Const webpack = require('webpack') const path = require('path') /* personal config */ const config = require('.. /config') /* utility */ const utils = require('./utils') / / const {merge} = require('webpack-merge') /* base configuration */ Const baseWebpackConfig = require('./webpack.base.conf') /* template */ const HtmlWebpackPlugin = Require ('html-webpack-plugin') /* const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') /* +1 */ const portfinder = require('portfinder') const HOST = process.env.HOST const PORT = process.env.port && Number(process.env.port) /* Dev config */ const devWebpackConfig = merge(baseWebpackConfig, { /* https://github.com/vuejs/vue-style-loader/issues/50 */ module: { rules: utils.styleLoaders({ sourceMap: Config. Dev. CssSourceMap})}, // Config.dev. devtool, // these devServer options should be customized in /config/index.js /* Configuration options */ devServer: HTML */ historyApiFallback: {rewrites: [{from: /.*/, to: Path. The posix. Join (config. Dev. AssetsPublicPath, 'index.html)}}], hot: true / * * / enable webpack module hot replacement properties, compress: True / * all services enable gzip compression * /, host: the host | | config. Dev. Host / * * / domain, port: the port | | config. Dev. Port / * * / port, the open: Config. Dev. AutoOpenBrowser / * whether to automatically open the browser * /, overlay: config. Dev. ErrorOverlay? {/ * warnings: false warning not to cover * /, errors: True /* Error full screen overlay */} : false /* Displays full screen overlay in the browser when a compiler error or warning occurs. It is disabled by default. If you only want to display compiler errors */, proxy: Config.dev. ProxyTable /* cross-domain config */}, / / https://webpack.docschina.org/configuration/stats/#stats-presets removed the -quiet / / in addition to the initial startup information, nothing written to the console. This also means that errors or warnings from Webpack are not visible. Stats: {preset: 'errors-only'}, // Throw a failed result when the first error occurs instead of tolerating it. -- This will force Webpack to exit its packaging process bail: true, // Verify that webpack has not been notified of file changes by using the --progress flag while running WebPack. WatchOptions: {poll: config.dev.poll, ignored: /node_modules/}, plugins: {poll: config.dev. [/* Environment set to development */ new webpack.defineplugin ({'process.env': require('../config/dev.env'), // https://github.com/JeffreyWay/laravel-mix/issues/2514 // https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags __VUE_OPTIONS_API__: 'true', __VUE_PROD_DEVTOOLS__: 'false'}), new webpack. HotModuleReplacementPlugin () / * * / open webpack hot update function, new FriendlyErrorsPlugin (), // https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true }) ], optimization: { splitChunks: { chunks: 'all'}, /* This plugin displays the relative path of the module when HMR is enabled. Recommended for development environments. */ moduleIds: 'named' /* NamedModulesPlugin module migration */, /* Webpack compilation error skip error phase, error after compilation */ emitOnErrors: True /* NoEmitOnErrorsPlugin module migration */}}) module.exports = new Promise((resolve, Reject) = > {/ * existence environment variable PORT is to use the environment variable, or set up good config. * / portfinder basePort = process. The env. The PORT | | config. Dev. The PORT portfinder.getPort((err, port) => { if (err) { reject(err) } else { // publish the new Port, Necessary for e2e tests process. The env. PORT = PORT / / replace PORT devWebpackConfig devServer. PORT = PORT / / add a good message devWebpackConfig.plugins.push( new FriendlyErrorsPlugin({ compilationSuccessInfo: { messages: [' When I wrote this code, only God and I knew what it was doing \n Now, only God knows ', 'Your application is running here: http://${devWebpackConfig.devServer.host}:${port}` ] }, onErrors: config.dev.notifyOnErrors ? utils.createNotifierCallback() : undefined, clearConsole: Resolve (devWebpackConfig)}})Copy the code

build/webpack.pro.conf.js

Const path = require('path') const webpack = require('webpack') / /config') /* utility */ const utils = require('./utils') / / const {merge} = require('webpack-merge') /* base configuration */ Const baseWebpackConfig = require('./webpack.base.conf') /* Assign static resource files to other directories */ const CopyWebpackPlugin = Dist */ const {require('copy-webpack-plugin') /* HTML */ const HtmlWebpackPlugin = require('html-webpack-plugin') /* dist */ const { CleanWebpackPlugin} = require(' cleanwebpack-plugin ') /* compress */ const TerserPlugin = require('terser-webpack-plugin') const webpackConfig = merge(baseWebpackConfig, { /* https://github.com/vuejs/vue-style-loader/issues/50 */ module: { rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) }, output: { filename: utils.getAssetPath('js/[name].[chunkhash].js'), chunkFilename: utils.getAssetPath('js/[id].[chunkhash].js') }, devtool: config.build.productionSourceMap ? config.build.devtool : If false / * generate SourceMap * /, / / https://webpack.docschina.org/configuration/stats/#stats-presets removed the -quiet / / in addition to the initial startup information, Nothing is written to the console. This also means that errors or warnings from webpack are invisible stats: {preset: 'errors-warnings'}, /* compression js */ optimization: {minimize: true, splitChunks: {chunks: 'all', // I'll try it myself: {libs: {name: 'chunk-libs', test: /[\\/]node_modules[\\/]/, priority: 10, chunks: 'initial' }, defaultVendors: { test: /\/src\//, name: 'rise', chunks: 'all', reuseExistingChunk: true }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } }, minimizer: [new TerserPlugin({terserOptions: {drop_console: true}}})]}, plugins: [ // http://vuejs.github.io/vue-loader/en/workflow/production.html new webpack.DefinePlugin({ 'process.env': require('../config/prod.env'), // https://github.com/JeffreyWay/laravel-mix/issues/2514 // https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags __VUE_OPTIONS_API__: 'true', __VUE_PROD_DEVTOOLS__: 'false' }), // see https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true, minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: The default options are 'none', 'auto', 'dependency', and '{function}' chunksSortMode: New CopyWebpackPlugin({patterns: [{from: path.resolve(__dirname, '../static')), to: config.build.assetsSubDirectory, globOptions: { ignore: ['.*'] } } ] }), new CleanWebpackPlugin() ] }) module.exports = webpackConfigCopy the code

config/dev.env.js

const { merge } = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"'
})

Copy the code

config/prod.env.js

module.exports = {
  NODE_ENV: '"production"'
}

Copy the code

config/index.js

// path = require('path') module.exports = {// build: {// path assetsSubDirectory: 'static', assetsPublicPath: '/' /* Resource public file */, assetsRoot: path.resolve(__dirname, '.. /dist') /* Output folder -- usually build */, productionSourceMap: false, // whether to generate sourcemap devtool: 'source-map'}, /* compile development mode */ dev: {// path assetsSubDirectory: 'static' /* Static file resource */, assetsPublicPath: '/', /* cross-domain */ proxyTable: {}, // server set host: 'localhost', // can be overridden by process.env.host 8080, // can be overridden by process.env.port [priority lower than environment configuration], if the PORT is in use, a free PORT will be determined autoOpenBrowser: false /* Whether the browser is automatically opened */, errorOverlay: True /* Whether code errors are overwritten on full-screen browsers */, notifyOnErrors: true /* Enable error prompts */, poll: False, / / monitor file https://webpack.docschina.org/configuration/watch/ showEslintErrorsInOverlay: UseEslint: true /* whether to useEslint */, /** * Source Maps */ devtool: 'eval-cheap-module-source-map' /* How to display developer console information */, /* CSS Sourcemaps */ cssSourceMap: false /* Whether to generate CSS file map */}}Copy the code