|

Aimee

Write the Code. Change the World.

自定义配置 vue 的 webpack.config.js

· 分享镜#vue

Vue.js核心库及loader的安装

webpack

  • webpack
    • 核心库
  • webpack-cli
    • 脚手架
  • webpack-dev-server
    • 服务
npm i webpack  webpack-cli webpack-dev-server -D

vue

  • vue
    • 核心包
  • vue-loader
    • webpack插件 处理.vue文件
  • vue-template-compiler
    • 编译.vue文件
npm i vue -S
npm i vue-loader -D

babel

  • @babel/core
    • 核心包
  • babel-loader
    • webpack 的loader插件
  • @vue/cli-plugin-babel
    • 包含js预设, 处理js兼容问题
npm i @babel/core babel-loader @vue/cli-plugin-babel -D

less和css

  • less
    • less库
  • less-loader
    • webpack 处理less的库
  • css-loader
    • webpack 处理css 样式的库
  • style-loader
    • 加入到html文件中
  • postcss
    • css兼容处理核心库
  • postcss-loader
    • webpack 处理css的loader
  • postcss-preset-env
    • 处理兼容的预设
    • 安装postcss-preset-env,无需再安装autoprefixer,由于postcss-preset-env已经内置了相关功能。
npm i less less-loader css-loader style-loader postcss postcss-loader postcss-preset-env -D

插件安装

clean-webpack-plugin

  • 清除插件
npm i clean-webpack-plugin -D

html-webpack-plugin

  • html 编译插件
npm i html-webpack-plugin -D

copy-webpack-plugin

  • 复制插件
npm i copy-webpack-plugin -D

配置webpack文件

配置文件设置

webpack.dev.js

  • 放置development 模式下的配置内容
module.exports = {
  mode: 'development'
  // ...
}

webpack.prod.js

  • 放置production 模式下的配置内容
module.exports = {
  mode: 'production'
   // ...
}

webpack.common.js

webpack-merge

  • 合并配置插件
npm i webpack-merge -D
  • 放置公共的配置内容
const merge = require('webpack-merge')
const devConfig = require('./webpack.dev')
const prodConfig = require('./webpack.prod')
const isProduction = process.env.NODE_ENV === 'production'

const commonConfig = {
 // ...
}

const baseConfig = isProduction ? prodConfig : devConfig
const defaultConfig = merge(commonConfig, baseConfig)

module.exports = defaultConfig

启动npm 命令

...  
"scripts": {
    "serve": "NODE_ENV=development webpack serve --config ./webpack.common.js",
    "build": "NODE_ENV=production webpack --config ./webpack.common.js",
  },
   ...

common配置项

入口配置

  • 入口设置参数为entry
entry: './src/main.js' // 相对路径

输出配置

  • 输出路径设置路径和具体文件名
  • 设置参数为output
  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, '../dist'),
    // publicPath: `//xxx.com/`, 
    chunkFilename: '[name].[contenthash].js'
  }

解析resolve

  • 设置默认扩展名的读取,可省略扩展名
  • 路径别名设置
  resolve: {
    extensions: [".js", ".json", '.ts', '.jsx', '.vue'],
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  }

module设置

css 和 less 文件配置(无压缩版)

 module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              esModule: false
            }
          }
        ]
      },
       {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'less-loader'
        ]
      },
      // ...
    ]
 }

图片和字体的配置

  • webpack5自带asset 可进行复制和处理,替代file-loader 和url-loader
module: {
    rules: [
			{
        test: /\.(png|svg|gif|jpe?g)$/,
        type: 'asset',
        generator: {
          filename: "img/[name].[hash:4][ext]"
        },
        parser: {
          dataUrlCondition: {
            maxSize: 30 * 1024
          }
        }
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: 'asset/resource',
        generator: {
          filename: 'font/[name].[hash:3][ext]'
        }
      },
      // ...
    ]
 }

js配置

  • 使用babel-loader
module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        use: ['babel-loader']
      }
        // ...
    ]
 }
  • babel-loader 的预设需要单独设置babel.config.js

vue配置

module: {
    rules: [
      {
        test: /\.vue$/,
        use: ['vue-loader']
      }
        // ...
    ]
 }

plugins配置

  • 开发和生成环境都需要用到html,需配置html-webpack-plugin插件
  • 需要使用到vue的插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const { DefinePlugin } = require('webpack')
plugins: [
    new HtmlWebpackPlugin({
      title: '设置的标题',
      template: './public/index.html'
    }),
   new DefinePlugin({
      BASE_URL: '"./"'
    }),
  	new VueLoaderPlugin()
  ]

common完整配置

const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const { DefinePlugin } = require('webpack')
const path = require('path')
const { merge } = require('webpack-merge')
const devConfig = require('./webpack.dev')
const prodConfig = require('./webpack.prod')
const isProduction = process.env.NODE_ENV === 'production'

const commonConfig = {
  entry: './src/main.js',
  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, '../dist'),
    // publicPath: `//xxx.com/`, 
    chunkFilename: '[name].[contenthash].js'
  },
  resolve: {
    extensions: [".js", ".json", '.ts', '.jsx', '.vue'],
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              esModule: false
            }
          },
          'postcss-loader'
        ]
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader',
          'less-loader'
        ]
      },
      {
        test: /\.(png|svg|gif|jpe?g)$/,
        type: 'asset',
        generator: {
          filename: "img/[name].[hash:4][ext]"
        },
        parser: {
          dataUrlCondition: {
            maxSize: 30 * 1024
          }
        }
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: 'asset/resource',
        generator: {
          filename: 'font/[name].[hash:3][ext]'
        }
      },
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        use: ['babel-loader']
      },
      {
        test: /\.vue$/,
        use: ['vue-loader']
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: '设置的标题',
      template: './public/index.html'
    }),
    new DefinePlugin({
      BASE_URL: '"./"'
    }),
    new VueLoaderPlugin()
  ]
}

const baseConfig = isProduction ? prodConfig : devConfig
const defaultConfig = merge(commonConfig, baseConfig)

module.exports = defaultConfig

dev 配置

mode

  • mode设置为development

devServer

  • hot
    • 配置是否开启热更新
  • port
    • 端口号
  • open
    • 是否自动打开浏览器
  • compress
    • 是否开启压缩
  • historyApiFallback
    • history模式刷新后是否重定向到入口页面
  • proxy
    • 设置代理
  devServer: {
    hot: true,
    hotOnly: true,
    port: 8080,
    open: false,
    compress: true,
    historyApiFallback: true,
    proxy: {
      '/api': {
        target: 'https://api.github.com',
        pathRewrite: { "^/api": "" },
        changeOrigin: true
      }
    }
  }

构建目标 target

告知 webpack 为目标(target)指定一个环境。默认值为 "browserslist",如果没有找到 browserslist 的配置,则默认为 "web"

 target: 'web',

devtool

  • 是否生成map文件
devtool: 'cheap-module-source-map',

development完整配置

module.exports = {
  mode: 'development',
  devtool: 'cheap-module-source-map',
  devServer: {
    hot: true,
    port: 8080,
    open: false,
    compress: true,
    historyApiFallback: true,
    proxy: {
      '/api': {
        target: 'https://api.github.com',
        pathRewrite: { "^/api": "" },
        changeOrigin: true
      }
    }
  }
}

prod 配置

mode

  • mode设置为production

专有插件设置

clean-webpack-plugin

  • 打包前清除目录文件
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
 // ...
  plugins: [
    new CleanWebpackPlugin(),
    // ...
  ]
}

copy-webpack-plugin

  • 复制静态资源文件

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
// ...
  plugins: [
// ...
    new CopyWebpackPlugin({
      patterns: [
        {
          from: 'public',
          globOptions: {
            ignore: ['**/index.html']
          }
        }
      ]
    })
  ]
}

production完整配置

const CopyWebpackPlugin = require('copy-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  mode: 'production',
  plugins: [
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: 'public',
          globOptions: {
            ignore: ['**/index.html']
          }
        }
      ]
    })
  ]
}

babel.config.js

  • 配置js兼容预设
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ]
}

postcss.config.js

  • 配置css兼容预设
module.exports = {
  plugins: [
    require('postcss-preset-env')
  ]
}

简易版package.json

{
  "name": "vue-app-base",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "NODE_ENV=development webpack serve --config ./webpack.common.js",
    "build": "NODE_ENV=production webpack --config ./webpack.common.js",
  },
  "dependencies": {},
  "devDependencies": {
    "@babel/core": "^7.16.0",
    "@vue/cli-plugin-babel": "^4.5.15",
    "babel-loader": "^8.2.3",
    "clean-webpack-plugin": "^4.0.0",
    "copy-webpack-plugin": "^10.0.0",
    "css-loader": "^6.5.1",
    "html-webpack-plugin": "^5.5.0",
    "less": "^4.1.2",
    "less-loader": "^10.2.0",
    "postcss": "^8.4.4",
    "postcss-loader": "^6.2.1",
    "postcss-preset-env": "^7.0.1",
    "style-loader": "^3.3.1",
    "vue": "^2.6.14",
    "vue-loader": "^15.9.8",
    "vue-template-compiler": "^2.6.14",
    "webpack": "^5.65.0",
    "webpack-cli": "^4.9.1",
    "webpack-dev-server": "^4.6.0",
    "webpack-merge": "^5.8.0"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

优化打包

css压缩和抽离

  • 安装css-minimizer-webpack-plugin 压缩css
  • 安装mini-css-extract-plugin 将css抽离 不能和style-loader 一起使用,会冲突
npm i css-minimizer-webpack-plugin mini-css-extract-plugin -D

  • 配置相关webpack.common.js
    • 调整style-loader 为 mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 需自行安装 需webpack5版本

···
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader, // 压缩css 文件
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              esModule: false
            }
          },
          'postcss-loader'
        ]
      },
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader']
      }
    ]
    ...
    plugins:[
     ...
       new MiniCssExtractPlugin({ // 抽离css 插件
         filename: "[name].css",
       }),
    ]
  }
      ···
  • webpack.prod.js的相关配置
...

const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); // 需自行安装 需webpack5版本  

module.exports = {
  mode: 'production',
  // ...
  optimization: {
    minimize: true, // 开启代码压缩
    minimizer: [
      new CssMinimizerPlugin() // 插件使用 cssnano 优化和压缩 CSS
    ]
  },
   // ...
}

js分包

  • 通过splitChunks 设置分包
 splitChunks: {
      chunks: 'all',  // async initial all
      minSize: 20000,
      maxSize: 20000,
      minChunks: 1,
      cacheGroups: {
        syVendors: {
          test: /[\\/]node_modules[\\/]/,
          filename: 'js/[id]_vendor.js',
          priority: -10,
        },
        default: {
          minChunks: 2,
          filename: 'js/chunk_[id].js',
          priority: -20,
        }
      }
    }

tree shaking

js shaking

  • 使用terser-webpack-plugin 插件,webpack5自带
  • 通过usedExports 开启
  • webpack.prod.js相关配置
const TerserPlugin = require("terser-webpack-plugin"); // webpack5自带插件

module.exports = {
  mode: 'production',
   // ... 
  optimization: {
    usedExports: true, // 开启tree shaking ,需结合terser-webpack-plugin 来实现
    minimize: true, // 开启代码压缩
    minimizer: [
      new TerserPlugin({
      	extractComments: false
      })// js代码压缩的插件
      // ...
    ]
   }
 }

css shaking

  • 安装 purgecss-webpack-plugin 去掉不需要的css
npm i  purgecss-webpack-plugin -D
  • 配置相关
const PurgecssPlugin = require('purgecss-webpack-plugin') // 需自行安装
module.exports = {
  mode: 'production',
   // ...
  plugins:[
     // ...
    new PurgecssPlugin({ // 移除未使用的css代码
      paths: glob.sync(`${path.resolve(__dirname, './src')}/**/*`, { nodir: true }),
    })
  ]
}

打包文件内容分析

  • 安装 插件 webpack-bundle-analyzer
npm i webpack-bundle-analyzer -D
  • 配置wepack.prod.js相关插件
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
module.exports = {
  mode: 'production',
  plugins: [
	//...
    new BundleAnalyzerPlugin()
  ]
}
  • 运行npm run build 可以看到打包的结果

eslint配置

安装配置

安装eslint

npm i eslint -D
  • 使用eslint 命令初始化eslint的配置
npx eslint --init
  • 根据提示完成操作:
    • To check syntax, find problems, and enforce code style(检查语法,发现问题,并强制代码样式)
    • JavaScript modules (import/export)
    • vue.js
    • typescript-no
    • Browser
    • Use a popular style guide(使用一个流行的风格指南)
    • Standard
    • 配置文件-JavaScript
  • 选择完成之后会自动安装相关插件
    • eslint-config-standard
    • eslint-plugin-import
    • eslint-plugin-node
    • eslint-plugin-promise
    • eslint-plugin-vue
  • 生成的配置文件如下
module.exports = {
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": [
    "plugin:vue/essential",
    "standard"
  ],
  "parserOptions": {
    "ecmaVersion": 13,
    "sourceType": "module"
  },
  "plugins": [
    "vue"
  ],
  "rules": {
    "vue/html-self-closing": [0]
  }
};

补充

eslint

  • 在wabpack中使用,还需要配置eslint-loader
  • 安装eslint-loader
npm i eslint-loader -D
  • webpack的配置
...
{
  test: /\.jsx?$/,
    exclude: /(node_modules|bower_components)/,
      use: ['babel-loader']
},
  {
    test: /\.jsx?$/,
      exclude: /(node_modules|bower_components)/,
        use: 'eslint-loader',
          enforce: "pre"
  },
  ...

babel-eslint

如果是 Vue 2.x 项目,配置了 eslint-plugin-vue 插件和 extends 后,template 校验还是会失效,因为不管是 ESLint 默认的解析器 Espree 还是 babel-eslint 都只能解析 JS,无法解析 template 的内容。

配置解析器

module.exports = {
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": [
    "plugin:vue/essential",
    "standard"
  ],
  "parserOptions": {
    "parser": "babel-eslint", // 补充
    "ecmaVersion": 13,
    "sourceType": "module"
  },
  "plugins": [
    "vue"
  ],
  "rules": {
    "vue/html-self-closing": [0]
  }
};


添加.eslintignore

  • 添加需要过滤的文件及目录
node_modules
dist
public

lint 校验命令

  • 在package.json中添加lint 命令
   "lint": "eslint --fix --ext .js,.vue src --ignore-path .eslintignore"

prettier配置

安装prettier

  • 安装prettier
  • 安装eslint-config-prettier 解决eslint rule的冲突
npm install prettier eslint-config-prettier -D

添加.prettierrc

  • 代码美化的规则
{
  "arrowParens": "always",
  "singleQuote": true,
  "trailingComma": "none",
  "semi": false
}

添加.prettierignore

  • 忽略需要修改的文件目录,和.gitignore类似
build/*.js
src/assets
public
dist
node_modules

配置package.json

 "prettier": "prettier --write ."

Git集成

pre-commit

  • 安装pre-commit 依赖
npm install pre-commit -D

lint-staged

  • 用于对 Git 暂存区中的文件执行代码检测
  • 安装依赖 npm install mrm@2 -D
  • 通过mrm安装lint-staged:npx mrm lint-staged
npm install mrm@2 -D
npx mrm lint-staged
  • package.json里多了两个开发依赖(husky和lint-staged)和一个prepare的脚本, 还有lint-staged命令:
    • husky可以用于实现各种 Git Hook。这里主要用到 pre-commit这个 hook,在执行 commit 之前,运行一些自定义操作
{
    "scripts": {
        "prepare": "husky install"
    },
    "devDependencies": {
        "husky": "^6.0.0",
        "lint-staged": "^11.0.0",
        "mrm": "^2.6.2",
        "prettier": "2.3.0"
    },
   "lint-staged": {
   	 	"*.js": "eslint --cache --fix",
    	"*.{js,css,md}": "prettier --write"
  	}
}
  • 根目录多了一个.husky的文件夹
  • 创建pre-commit 钩子
npx husky add .husky/pre-commit "npx lint-staged"
  • 添加package.json 中husky 配置项
 "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  • 如果.git 和项目文件不在一个文件
# 启动 git hooks
cd .. && husky install shop-web/.husky

# 添加 pre-commit 钩子
npx husky add .husky/pre-commit "cd shop-web && npx lint-staged"

# 安装 lint-staged
npm install lint-staged -D

添加commit-msg脚本

npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
  • commit-msg脚本内容如下:
#!/bin/sh

"$(dirname "$0")/_/husky.sh"

npx --no-install commitlint --edit "$1"

定制提交规范

规范 commit 为 git commit -m ''feat(*):提交名称'

  • 安装commitlint 插件
npm install --save-dev @commitlint/config-conventional @commitlint/cli
  • 设置package.json相关配置项
    • 添加commitlint
    • 添加husky 的commit-msg 配置项
   "commitlint": {
    "extends": [
      "@commitlint/config-conventional"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  },
  "lint-staged": {
    "*.js": "eslint --cache --fix",
    "*.{js,css,md}": "prettier --write"
  }

最终配置

package.json

{
  "name": "vue2-webpack-demo",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "NODE_ENV=development webpack serve --config ./webpack.common.js",
    "build": "NODE_ENV=production webpack --config ./webpack.common.js",
    "lint": "eslint --fix --ext .js,.vue src --ignore-path .eslintignore  ",
    "prettier": "prettier --write .",
    "prepare": "husky install"
  },
  "dependencies": {},
  "devDependencies": {
    "@babel/core": "^7.16.0",
    "@babel/preset-env": "^7.16.4",
    "@vue/cli-plugin-babel": "^4.5.15",
    "babel-eslint": "^10.1.0",
    "babel-loader": "^8.2.3",
    "clean-webpack-plugin": "^4.0.0",
    "copy-webpack-plugin": "^10.0.0",
    "css-loader": "^6.5.1",
    "css-minimizer-webpack-plugin": "^3.2.0",
    "eslint": "^7.32.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-config-standard": "^16.0.3",
    "eslint-loader": "^4.0.2",
    "eslint-plugin-import": "^2.25.3",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-promise": "^5.2.0",
    "eslint-plugin-vue": "^8.2.0",
    "glob": "^7.2.0",
    "html-webpack-plugin": "^5.5.0",
    "husky": "^7.0.4",
    "less": "^4.1.2",
    "less-loader": "^10.2.0",
    "lint-staged": "^12.1.2",
    "mini-css-extract-plugin": "^2.4.5",
    "mrm": "^2.6.2",
    "postcss": "^8.4.4",
    "postcss-loader": "^6.2.1",
    "postcss-preset-env": "^7.0.1",
    "pre-commit": "^1.2.2",
    "prettier": "^2.5.1",
    "purgecss-webpack-plugin": "^4.1.3",
    "vue": "^2.6.14",
    "vue-loader": "^15.9.8",
    "vue-template-compiler": "^2.6.14",
    "webpack": "^5.65.0",
    "webpack-bundle-analyzer": "^4.5.0",
    "webpack-cli": "^4.9.1",
    "webpack-dev-server": "^4.6.0",
    "webpack-merge": "^5.8.0"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ],
  "commitlint": {
    "extends": [
      "@commitlint/config-conventional"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  },
  "lint-staged": {
    "*.js": "eslint --cache --fix",
    "*.{js,css,md}": "prettier --write"
  }
}

webpack.common.js

const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 需自行安装 需webpack5版本
const { DefinePlugin } = require('webpack')
const path = require('path')
const { merge } = require('webpack-merge')

const devConfig = require('./webpack.dev')
const prodConfig = require('./webpack.prod')
const isProduction = process.env.NODE_ENV === 'production'

const commonConfig = {
  entry: './src/main.js',
  output: {
    filename: '[name].[contenthash:8].js',
    path: path.resolve(__dirname, './dist'),
    // publicPath: `//xxx.com/`,
    chunkFilename: '[name].[contenthash:8].js'
  },
  resolve: {
    extensions: ['.js', '.json', '.ts', '.jsx', '.vue'],
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader, // 压缩css 文件
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              esModule: false
            }
          },
          'postcss-loader'
        ]
      },
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader']
      },
      {
        test: /\.(png|svg|gif|jpe?g)$/,
        type: 'asset',
        generator: {
          filename: 'img/[name].[contentHash:4][ext]'
        },
        parser: {
          dataUrlCondition: {
            maxSize: 30 * 1024
          }
        }
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: 'asset/resource',
        generator: {
          filename: 'font/[name].[contentHash:3][ext]'
        }
      },
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        use: ['babel-loader']
      },
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        use: 'eslint-loader',
        enforce: 'pre'
      },
      {
        test: /\.vue$/,
        use: ['vue-loader']
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({ // 抽离css 插件
      filename: "[name].[contentHash:4].css",
    }),
    new HtmlWebpackPlugin({
      title: '设置的标题',
      template: './public/index.html'
    }),
    new DefinePlugin({
      BASE_URL: '"./"'
    }),
    new VueLoaderPlugin()
  ]
}

const baseConfig = isProduction ? prodConfig : devConfig
const defaultConfig = merge(commonConfig, baseConfig)

module.exports = defaultConfig

webpack.dev.js

module.exports = {
  mode: 'development',
  devtool: 'cheap-module-source-map',
  devServer: {
    hot: true,
    port: 8080,
    open: false,
    compress: true,
    historyApiFallback: true,
    proxy: {
      '/api': {
        target: 'https://api.github.com',
        pathRewrite: { '^/api': '' },
        changeOrigin: true
      }
    }
  }
}

webpack.prod.js

const CopyWebpackPlugin = require('copy-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const TerserPlugin = require("terser-webpack-plugin"); // webpack5自带插件
const PurgecssPlugin = require('purgecss-webpack-plugin') // 需自行安装
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); // 需自行安装 需webpack5版本  
const glob = require('glob')
const path = require('path')

module.exports = {
  mode: 'production',
  optimization: {
    usedExports: true, // 开启tree shaking ,需结合terser-webpack-plugin 来实现
    minimize: true, // 开启代码压缩
    minimizer: [
      new TerserPlugin({
        extractComments: false
      }),// js代码压缩的插件
      new CssMinimizerPlugin() // 插件使用 cssnano 优化和压缩 CSS
    ],
    splitChunks: {
      chunks: 'all',  // async initial all
      minSize: 20000,
      maxSize: 20000,
      minChunks: 1,
      cacheGroups: {
        syVendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
        },
        default: {
          minChunks: 2,
          priority: -20,
        }
      }
    }
  },
  plugins: [
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: 'public',
          globOptions: {
            ignore: ['**/index.html']
          }
        }
      ]
    }),
    new PurgecssPlugin({ // 移除未使用的css代码
      paths: glob.sync(`${path.resolve(__dirname, './src')}/**/*`, { nodir: true }),
    }),
    new BundleAnalyzerPlugin()
  ]
}

babel.config.js

module.exports = {
  presets: ['@vue/cli-plugin-babel/preset']
}

postcss.config.js

module.exports = {
  plugins: [require('postcss-preset-env')]
}

.prettierrc

{
  "arrowParens": "always",
  "singleQuote": true,
  "trailingComma": "none",
  "semi": false
}

.eslintrc.js

module.exports = {
  env: {
    browser: true,
    es2021: true
  },
  extends: ['plugin:vue/essential', 'standard'],
  parserOptions: {
    parser: 'babel-eslint',
    ecmaVersion: 13,
    sourceType: 'module'
  },
  plugins: ['vue'],
  rules: {
    'vue/html-self-closing': [0]
  }
}

.eslintignore

node_modules
dist
public

demo

https://github.com/Aimee1608/vue2-webpack-demo

评论24

登录后参与评论。

  • 游客

    1

  • 游客

    2

  • 游客

    3

  • 游客

    4

  • 游客

    哈哈

  • 游客

    囧

  • 游客

    微笑

  • 晚自习
    晚自习回复

    1

  • 晚自习
    晚自习回复

    2嘻嘻

  • 游客

    手动风水多

  • 游客

    大苏打

  • 游客

    会突然

  • 游客

    左哼哼

  • 游客

    1可爱

  • aneng
    aneng回复

    11

  • aneng
    aneng回复

    ??

  • aneng
    aneng回复

    aa

  • aneng
    aneng回复

    11

  • 游客

    666

  • 游客

    1111

  • 游客

    11

  • 游客

    佬 用下你的前端写一个前后端项目

  • 游客

    完了 登录不上去了 登录报错了

  • 游客

    11

回到顶部