使用Webpack5搭建Vue开发环境项目实战!

2,271 阅读7分钟

前言

webpack5.0项目中的配置如下,直接CV可以运行使用!偶尔的整理一下可以给开发带来一点点🤏帮助! gitee地址:gitee.com/licong777/w…

以下是我的package.json文件,配置项目所需要的依赖。可以参考:

{
  "name": "webpack5",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "serve": "cross-env NODE_ENV=development webpack serve --config build/webpack.dev.config.js",
    "build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.14.8",
    "@babel/plugin-proposal-decorators": "^7.14.5",
    "@babel/plugin-proposal-optional-chaining": "^7.14.5",
    "@babel/plugin-transform-runtime": "^7.14.5",
    "@babel/polyfill": "^7.12.1",
    "@babel/preset-env": "^7.14.8",
    "@babel/runtime-corejs2": "^7.14.8",
    "autoprefixer": "^10.3.1",
    "babel-loader": "^8.2.2",
    "compression-webpack-plugin": "^8.0.1",
    "copy-webpack-plugin": "^9.0.1",
    "cross-env": "^7.0.3",
    "css-loader": "^6.2.0",
    "css-minimizer-webpack-plugin": "^3.0.2",
    "html-minimizer-webpack-plugin": "^3.1.1",
    "html-webpack-plugin": "^5.3.2",
    "less": "^4.1.1",
    "less-loader": "^10.0.1",
    "mini-css-extract-plugin": "^2.1.0",
    "path-browserify": "^1.0.1",
    "postcss-loader": "^6.1.1",
    "sass-resources-loader": "^2.2.3",
    "style-loader": "^3.2.1",
    "terser-webpack-plugin": "^5.1.4",
    "vue-loader": "^15.9.6",
    "vue-template-compiler": "^2.6.14",
    "webpack": "^5.46.0",
    "webpack-cli": "^4.7.2",
    "webpack-dev-server": "^3.11.2",
    "webpack-merge": "^5.8.0"
  }
}

开始搭建

运行 webpack 5 的 Node.js 最低版本是 10.13.0 (LTS)。安装依赖方式采用淘宝镜像服务没有的话可以执行安装:npm i -g cnpm -registry=http://registry.npm.taobao.org

首先执行cnpm init -y 生成package.json初始化项目配置文件, 安装webpack相关依赖包

cnpm i webpack webpack-dev-server webpack-merge -D

webpack可以看做是模块打包机。webpack-cli简易客户端,用来以webpack协议连接相应服务。webpack-dev-server是webpack官方提供的一个小型express服务器, 为webpack打包生成的资源文件提供web服务。webpack-merge是用于合并不同的环境的文件使用。

核心属性配置

  • entry

开始应用程序打包过程的一个或多个起点。如果传入数组,则会处理所有条目。在这里可以引入@babel/polyfill插件,用以转换新的api,解决语法兼容性问题

entry: [
    '@babel/polyfill',
    resolve('../src/main.js')
  ]
  • output

指示 webpack 如何去打包输出,可以在这里配置相关属性,chunkFilename是配合vue路由懒加载的webpackChunkName去使用,用来生成输出的文件名。v5版本新增clean属性可以清除打包目录。

 output: {
    path: resolve('../dist'),
    filename: 'js/[name].js',
    chunkFilename: 'js/[name].js',
    clean: true
  },
  • module

配置属性去处理项目中的不同类型模块,文件转换的loader在module.rules里配置。

处理js文件

@babel/core是转译器本身,提供了babel的转译API。babel-loader就是调用这些API来完成转译js过程的, @babel/preset-env包括:es2017、es1016、es2015等一些常用的插件预设。其他的一些用到的插件可以选择性安装,并且在.babelrc文件中添加

cnpm i @babel/core babel-loader @babel/preset-env -D

{
        test: /\.jsx?$/,
        exclude: [resolve('../node_modules')],
        use: [
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true
            }
          }
        ]
}

.babelrc文件配置示例:

{
  "presets": [
    "@babel/preset-env"
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": 2
      }
    ],
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    "@babel/plugin-proposal-optional-chaining"
  ]
}

处理css文件

安装相关loader

postcss-loader aotoprefixer用来添加css浏览器前缀解决兼容问题,还需要配置postcss.config.js文件。开发环境使用style-loader运行更快,生产环境使用mini-css-extract-plugin来提取css文件性能好些。配置如下

cnpm i css-loader less less-loader style-loader 
postcss-loader aotoprefixer mini-css-extract-plugin  sass-resources-loader -D

{
        test: /\.(css|less)$/,
        exclude: [resolve('../node_modules')],
        use: [
          devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'less-loader',
          {
            loader: 'sass-resources-loader', // 提取公共的样式变量到全局使用
            options: {
              resources: [
                resolve('../src/assets/styles/common.less')
              ]
            }
          },

postcss.config.js文件配置示例

module.exports = { 
  plugins: [ 
    require('autoprefixer') 
  ] 
} 

处理图片,字体等文件

不再需要安装url-loader,file-loader

{
        test: /\.(png|jpg|jpeg|svg|gif)$/,
        type: 'asset/inline' // 导出一个资源的 data URI。之前通过使用 url-loader 实现。
      },
      {
        test: /\.(ttf|otf|woff2?|eot)$/,
        type: 'asset/resource', //  导出一个单独的文件, 之前通过使用 file-loader 实现。
        generator: {
          filename: 'fonts/[name][ext]' // 配置导出目录文件名
        }
  • plugins

用于以各种方式自定义 webpack 构建过程。webpack 附带了各种内置插件,也可自己按需求安装。以下仅个别示例:

安装报错友好提示插件:cnpm i friendly-errors-webpack-plugin node-notifier -D

安装打包后项目分析的可视化插件:cnpm i webpack-bundle-analyzer -D

const webpack = require('webpack')
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin')
const notifier = require('node-notifier')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
  
plugins: [
    new VueLoaderPlugin(), // 处理vue文件需安装 vue-loader vue-template-compiler
    new HtmlWebpackPlugin({ // 生成html文件
      template: resolve('../public/index.html'),
      favicon: resolve('../public/lyf.jpg')
    }),
    new MiniCssExtractPlugin({ // 将 CSS 提取到单独的文件中
      filename: 'css/[name].css'
    }),
    new webpack.ProgressPlugin(),  // 展示启动/打包进度条
    new CopyWebpackPlugin({ // 将不需要构建的资源文件拷贝到打包后dist目录
      patterns: [
        {
          from: resolve('../src/statics/dependences'),
          to:  resolve('../dist/dependences')
        }
      ]
    }),
    new CompressionWebpackPlugin({ // 开启gzip压缩
      test: /\.(js|css)$/,
    }),
  new webpack.HotModuleReplacementPlugin() // 配置热更新插件 
  new FriendlyErrorsWebpackPlugin({
      onErrors: (severity, errors) => {
        if (severity !== 'error') {
          return
        }
        const error = errors[0]
        notifier.notify({
          title: "Webpack error",
          message: severity + ': ' + error.name,
          subtitle: error.file || ''
        })
      }
    }),
   new BundleAnalyzerPlugin({ analyzerMode: 'disabled', generateStatsFile: true, })
]
  • mode

提供 mode 配置选项,告知 webpack 使用相应模式的内置优化,开发环境:development

生产环境:production。如果没有设置,webpack 会给 mode 的默认值设置为 production

  • resolve

配置选项能设置模块如何被解析,常用的有extensions,alias等属性。此外,V5版本移除了node内置模块的自动引入,页面有使用到的相关模块需要在resolve.fallback引入并安装该依赖,例如:path

  resolve: {
    extensions: ['.vue', '.js', '.less'], // 按顺序解析,能够使用户在引入模块时不带扩展
    alias: { // 配置路径别名
      '@': resolve('../src')
    },
    fallback: { // 这里引入浏览器页面中使用的node内置模块
      path: require.resolve('path-browserify')
    }
  }
  • stats

    stats: { // 精简打包运行时控制台输出信息 preset: 'minimal', // 预设 builtAt: true, errorDetails: true, moduleTrace: true },

  • devServer

开发服务器,用以并提供一个本地服务

  devServer: {
    host: 'localhost',
    port: 8080,
    open: true,
    hot: true, // 启用 webpack  HotModuleReplacement 功能
    compress: true, // 开启压缩
    historyApiFallback: true,
    contentBase: resolve('../dist'), // 起服务文件路径
    proxy: { // 配置相关代理
      '/api': {
        target: 'http://localhost:8080',
        secure: false,
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    },
  },
  • optimization

生产环境优化压缩css,html,js一些文件可以在optimization.minimizer中添加此插件

cnpm i html-minimizer-webpack-plugin css-minimizer-webpack-plugin terser-webpack-plugin -D

  optimization: {
    minimize: true,
    minimizer: [
      new HtmlMinimizerPlugin(), // 压缩html
      new CssMinimizerPlugin(), // // 压缩css
      new TerserWebpackPlugin({ // 压缩js
        parallel: true,
        extractComments: false,
        terserOptions: {
          compress: {
            drop_console: true, // 移除console
            drop_debugger: true // 移除debugger
          },
          format: {
            comments: false  // 移除注释
          }
        }
      })
    ],
    splitChunks: {
      chunks: 'all', // 这表明将选择哪些 chunk 进行优化
      name: 'chunks'  // 拆分 chunk 的名称
    }
  },
  • devtool

此选项控制是否生成,以及如何生成 source map

开发环境建议配置eval-cheap-module-source-map ,  生产环境可以省略此配置

  • performance

配置如何展示性能提示。默认是250K会有警告提示。例如以下设置,如果一个css/js资源超过 5MB,webpack 会对此输出一个警告来通知你

  performance: { 
    hints: 'warning', // 可选值:warning、error、false
    maxEntrypointSize: 5 * 1024 * 1024, // 单位为字节
    maxAssetSize: 5 * 1024 * 1024, // 单位为字节
    assetFilter: function (assetFilename) {
      return assetFilename.endsWith('.js') || assetFilename.endsWith('.css')
    },
  },
  • externals

提供了「从输出的 bundle 中排除依赖」的方法,将防止把某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖。可以极大优化压缩打包后文件大小以提高页面响应速度

如下string形式的配置:key是从页面引入的包名称 , value表示该第三方包抛出的全局变量

  externals: { //将需要忽略打包的都写在这个里面,但前提是index.html文件里面必须script引入
    'vue': 'Vue',
    'vue-router': 'VueRouter',
    'vuex': 'Vuex',
    'axios': 'axios',
    'lodash': '_',
    'element-ui': 'ELEMENT',
  }

总得来说,externals配置就是为了使import lodash from 'lodash'这句代码,在本身不引入lodash的情况下,能够在各个环境都能解释执行。

Webpak5对比4.0版本的变化

  1.  webpack5中移除了nodejs核心模块的polyfill自动引入,所以需要手动引入,如果打包过程中文件中有使用到nodejs核心模块,webpack会提示进行相应配置。例如:path 需要在resolve.fallback中添加配置: path: require.resolve('path-browserify'),并安装对应依赖包 path-browserify

  2. 不再需要clean-webpack-plugin插件清除打包后的dist目录, 只需在output属性里添加:clean:true即可

  3. 移除了file-loader, url-loader, 取而代之:asset module

  4. 输出的文件名hash值使用已废弃,可以使用contenthash代替。webpack v5版本修复了css热更新问题,但是使用 mini-css-extract-plugin 插件设置filename参数不能带hash值,否则输出的文件找不到, 不带contenthash值情况下热更新是正常的,不会报错。

  5. 安装webpack-dev-server服务后,项目启动命令变更为:webpack serve

  6. 多环境的配置需要引入webpack-merge插件进行文件的合并,引入的的merge方法改为 const { merge } = require('webpack-merge')

  7. 移除了webpack的内置方法 NamedChunksPlugin , 无需配置,使用热更新时控制台会默认显示模块的相对路径

  8. 生产环境压缩处理css html文件, 优化和压缩css可以使用css-minimizer-webpack-plugin以取代之前的mini-css-assets-webpack-plugin,  相比在 source mapsassets 中使用查询字符串会更加准确,支持缓存和并发模式下运行。在optimization.minimizer中添加使用

    cnpm i css-minimizer-webpack-plugin html-minimizer-webpack-plugin -D
    
    new HtmlMinimizerPlugin()
    new CssMinimizerPlugin()
    
  9. 生产环境压缩处理js文件,不再使用uglifyjs-webpack-plugin,这个插件不支持对ES6的语法压缩,webpack v5 自带最新的terser-webpack-plugin 如果需要修改内部配置还需要单独安装。

    cnpm i terser-webpack-plugin -D
    
    new TerserWebpackPlugin()