webpack5构建vue
必要环境
安装ndejs
我们需要安装node 如果没有安装则安装 安装过则跳过
执行
1node -v 2npm -v

初始化项目文件夹
新建一个空的项目
执行 npm init -y 初始化
npm init -y
会生成一个package.json

安装webpack以及 html-webpack-plugin
控制台执行
npm i webpack webpack-cli webpack-dev-server html-webpack-plugin -D
安装babel-loader
babel可以将我们的代码向下适配
1npm i babel-loader @babel/core @babel/preset-env @babel/polyfill core-js@3 -D 2
安装 css-lodaer
支持less
npm install css-loader style-loader sass-loader postcss-loader autoprefixer less-loader -D
安装 mini-css-extract-plugin css-minimizer-webpack-plugin
用来抽离压缩css 代码
npm i mini-css-extract-plugin css-minimizer-webpack-plugin -D
项目依赖 (面还有需要安装的)
1 "devDependencies": { 2 "@babel/core": "^7.16.12", 3 "@babel/polyfill": "^7.12.1", 4 "@babel/preset-env": "^7.16.11", 5 "@element-plus/icons": "^0.0.11", 6 "@vue/cli-plugin-babel": "^4.5.15", 7 "@vue/compiler-sfc": "^3.2.29", 8 "autoprefixer": "^10.4.2", 9 "babel-eslint": "^10.1.0", 10 "babel-loader": "^8.2.3", 11 "copy-webpack-plugin": "^10.2.1", 12 "core-js": "^3.20.3", 13 "css-loader": "^6.5.1", 14 "css-minimizer-webpack-plugin": "^3.4.1", 15 "element-plus": "^1.3.0-beta.9", 16 "eslint": "^7.32.0", 17 "eslint-loader": "^4.0.2", 18 "eslint-plugin-vue": "^8.4.0", 19 "file-loader": "^6.2.0", 20 "html-webpack-plugin": "^5.5.0", 21 "less-loader": "^10.2.0", 22 "lodash": "^4.17.21", 23 "mini-css-extract-plugin": "^2.5.3", 24 "postcss-loader": "^6.2.1", 25 "sass": "^1.26.5", 26 "sass-loader": "^8.0.2", 27 "style-loader": "^3.3.1", 28 "terser-webpack-plugin": "^5.3.0", 29 "unplugin-auto-import": "^0.5.11", 30 "unplugin-vue-components": "^0.17.15", 31 "url-loader": "^4.1.1", 32 "vue": "^3.2.29", 33 "vue-loader": "^16.1.0", 34 "vue-router": "^4.0.12", 35 "vue-style-loader": "^4.1.3", 36 "vuex": "^4.0.2", 37 "webpack": "^5.67.0", 38 "webpack-cli": "^4.9.2", 39 "webpack-dev-server": "^4.7.3" 40 }
创建多个目录
创建多个文件夹 方便存放不同资源 参考vue-cli脚手架生成的
根目录下新建 webpack.config.js
src下创建main.ts 以及 App.vue
如下

public 目录下
我们放入一个ico文件

创建模板 html文件
webpack5内置了clean output开启即可
在 public目录下新建 index.html
1<!DOCTYPE html> 2<html lang=""> 3<head> 4 <meta charset="UTF-8"> 5 <link rel="icon" href="<%= BASE_URL %>favicon.ico"> 6 <title><%= htmlWebpackPlugin.options.title %></title> 7</head> 8<body> 9<noscript> 10 <strong><%= htmlWebpackPlugin.options.title %>:请检查js是否正常启用</strong> 11</noscript> 12<div id="app"></div> 13</body> 14</html> 15
开始构建vue项目
安装 vue-loader等
1npm i vue-loader vue-template-compiler vue@next vuex@next vue-router@next -D 2npm install terser-webpack-plugin copy-webpack-plugin -D
配置webpack
webpack5内置了 clean 和 热更新
开启方式 在devServer配置
1devServer: { 2 hot: true, 3 liveReload: true 4},
在 webpack.config.js 文件中
1const path = require('path') 2const HtmlWebpackPlugin = require('html-webpack-plugin') 3const { VueLoaderPlugin } = require('vue-loader') 4const MiniCssExtract = require('mini-css-extract-plugin') 5const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') //生产环境 6const TerserPlugin = require('terser-webpack-plugin') 7const CopyWebpackPlugin = require('copy-webpack-plugin') 8 9module.exports = (env) => { 10 return { 11 devServer: { 12 port: 8888, 13 hot: true, 14 liveReload: true 15 }, 16 17 mode: env.development ? 'development' : 'production', 18 19 resolve: { 20 alias: { 21 '@': path.resolve(__dirname, './src') 22 } 23 }, 24 25 entry: './src/main.js', 26 27 output: { 28 filename: "js/[name].[contenthash].js", 29 // path: path.resolve(__dirname, 'dist/js'), 30 clean: true, 31 publicPath: "./" 32 }, 33 module: { 34 rules: [ 35 { 36 test: /\.vue$/, 37 loader: 'vue-loader' 38 }, 39 { 40 test: /\.js$/, 41 exclude: file => ( 42 /node_modules/.test(file) && 43 !/\.vue\.js/.test(file) 44 ), 45 use: [ 46 { 47 loader: 'babel-loader', 48 options: { 49 presets: [ 50 [ 51 '@babel/preset-env', 52 { 53 targets: [ 54 'last 1 version', //浏览器最新的一个版本 55 '> 1%' //代码使用超过1% 56 ], 57 useBuiltIns: 'usage', 58 corejs: 3 59 } 60 ] 61 ] 62 } 63 }, 64 { 65 loader: "eslint-loader" 66 } 67 ] 68 }, 69 { 70 test: /\.(css|scss)$/, 71 use: [env.development ? 'vue-style-loader' 72 : MiniCssExtract.loader, 73 { 74 loader: 'css-loader' 75 }, 76 { 77 loader: 'sass-loader' 78 } 79 ] 80 }, 81 { 82 test: /\.(woff|woff2|eot|ttf|otf)$/, 83 type: 'asset/resource' 84 }, 85 { 86 test: /\.(png|jpg|gif)$/, 87 use: [ 88 { 89 loader: "file-loader", 90 options: { 91 name:'img/[name].[hash].[ext]', 92 } 93 } 94 95 96 ] 97 } 98 ] 99 }, 100 101 optimization: { 102 minimizer: [ 103 new CssMinimizerPlugin(), 104 new TerserPlugin() 105 ] 106 }, 107 108 plugins: [ 109 new HtmlWebpackPlugin({ 110 title: "小型vue应用", 111 template: "public/index.html", 112 filename: "index.html", 113 baseUrl: './icon/favicon.ico' 114 }), 115 new CopyWebpackPlugin({ 116 patterns:[ 117 { 118 from: path.resolve(__dirname, './public/icon'), 119 to: path.resolve(__dirname, './dist/icon'), 120 } 121 ] 122 }), 123 new MiniCssExtract({ 124 filename: 'css/style.css' 125 }), 126 new VueLoaderPlugin() 127 ] 128 129 } 130 131} 132
修改package.json

初始化 eslint
eslint --init
选择 检查找到问题
选择 js 浏览器环境 不用ts
拆分配置文件
开发环境
1const path = require('path') 2const HtmlWebpackPlugin = require('html-webpack-plugin') 3const { VueLoaderPlugin } = require('vue-loader') 4 5module.exports = { 6 devServer: { 7 port: 8888, 8 hot: true, 9 liveReload: true 10 }, 11 12 mode: 'development', 13 14 resolve: { 15 alias: { 16 '@': path.resolve(__dirname, './src') 17 } 18 }, 19 20 entry: './src/main.js', 21 22 output: { 23 filename: "js/[name].[contenthash].js", 24 // path: path.resolve(__dirname, 'dist/js'), 25 publicPath: "/" 26 }, 27 module: { 28 rules: [ 29 { 30 test: /\.vue$/, 31 loader: 'vue-loader' 32 }, 33 { 34 test: /\.js$/, 35 exclude: file => ( 36 /node_modules/.test(file) && 37 !/\.vue\.js/.test(file) 38 ), 39 use: [ 40 { 41 loader: 'babel-loader', 42 options: { 43 presets: [ 44 [ 45 '@babel/preset-env', 46 { 47 targets: [ 48 'last 1 version', //浏览器最新的一个版本 49 '> 1%' //代码使用超过1% 50 ], 51 useBuiltIns: 'usage', 52 corejs: 3 53 } 54 ] 55 ] 56 } 57 }, 58 { 59 loader: "eslint-loader" 60 } 61 ] 62 }, 63 { 64 test: /\.(css|scss)$/, 65 use: ['vue-style-loader', 66 { 67 loader: 'css-loader' 68 // , 69 // options: { 70 // modules:{ 71 // localIdentName: '[local]_[hash:base64:8]' 72 // } 73 // } 74 }, 75 { 76 loader: 'sass-loader' 77 // options: { 78 // // sass-loader version >= 8 79 // sassOptions: { 80 // indentedSyntax: true 81 // } 82 // } 83 } 84 ] 85 }, 86 { 87 test: /\.(woff|woff2|eot|ttf|otf)$/, 88 type: 'asset/resource' 89 }, 90 { 91 test: /\.(png|jpg|gif)$/, 92 use: [ 93 // { 94 // loader:'url-loader', 95 // options:{ 96 // limit:4096, 97 // outputPath:'./img', 98 // name:'[name].[hash].[ext]', 99 // } 100 // }, 101 { 102 loader: "file-loader", 103 options: { 104 name:'img/[name].[hash].[ext]', 105 } 106 } 107 108 109 ] 110 } 111 ] 112 }, 113 114 plugins: [ 115 new HtmlWebpackPlugin({ 116 title: "小型vue应用", 117 template: "public/index.html", 118 }), 119 new VueLoaderPlugin() 120 ] 121 122} 123
生产环境
1const path = require('path') 2const HtmlWebpackPlugin = require('html-webpack-plugin') 3const { VueLoaderPlugin } = require('vue-loader') 4const MiniCssExtract = require('mini-css-extract-plugin') 5const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') //生产环境 6const TerserPlugin = require('terser-webpack-plugin') 7const CopyWebpackPlugin = require('copy-webpack-plugin') 8 9module.exports = () => { 10 11 return { 12 13 mode: 'production', 14 15 resolve: { 16 alias: { 17 '@': path.resolve(__dirname, './src') 18 } 19 }, 20 21 entry: './src/main.js', 22 23 output: { 24 filename: "js/[name].[contenthash].js", 25 // path: path.resolve(__dirname, 'dist/js'), 26 clean: true, 27 publicPath: "./" 28 }, 29 module: { 30 rules: [ 31 { 32 test: /\.vue$/, 33 loader: 'vue-loader' 34 }, 35 { 36 test: /\.js$/, 37 exclude: file => ( 38 /node_modules/.test(file) && 39 !/\.vue\.js/.test(file) 40 ), 41 use: [ 42 { 43 loader: 'babel-loader', 44 options: { 45 presets: [ 46 [ 47 '@babel/preset-env', 48 { 49 targets: [ 50 'last 1 version', //浏览器最新的一个版本 51 '> 1%' //代码使用超过1% 52 ], 53 useBuiltIns: 'usage', 54 corejs: 3 55 } 56 ] 57 ] 58 } 59 }, 60 { 61 loader: "eslint-loader" 62 } 63 ] 64 }, 65 { 66 test: /\.(css|scss)$/, 67 use: [ MiniCssExtract.loader, 68 { 69 loader: 'css-loader' 70 // , 71 // options: { 72 // modules:{ 73 // localIdentName: '[local]_[hash:base64:8]' 74 // } 75 // } 76 }, 77 { 78 loader: 'sass-loader' 79 // options: { 80 // // sass-loader version >= 8 81 // sassOptions: { 82 // indentedSyntax: true 83 // } 84 // } 85 } 86 ] 87 }, 88 { 89 test: /\.(woff|woff2|eot|ttf|otf)$/, 90 type: 'asset/resource' 91 }, 92 { 93 test: /\.(png|jpg|gif)$/, 94 use: [ 95 // { 96 // loader:'url-loader', 97 // options:{ 98 // limit:4096, 99 // outputPath:'./img', 100 // name:'[name].[hash].[ext]', 101 // } 102 // }, 103 { 104 loader: "file-loader", 105 options: { 106 name:'img/[name].[hash].[ext]', 107 } 108 } 109 110 111 ] 112 } 113 ] 114 }, 115 116 optimization: { 117 minimizer: [ 118 new CssMinimizerPlugin(), 119 new TerserPlugin() 120 ] 121 }, 122 123 plugins: [ 124 new HtmlWebpackPlugin({ 125 title: "小型vue应用", 126 template: "public/index.html", 127 filename: "index.html", 128 baseUrl: './icon/favicon.ico' 129 }), 130 new CopyWebpackPlugin({ 131 patterns:[ 132 { 133 from: path.resolve(__dirname, './public/icon'), 134 to: path.resolve(__dirname, './dist/icon'), 135 } 136 ] 137 }), 138 new MiniCssExtract({ 139 filename: 'css/style.css' 140 }), 141 new VueLoaderPlugin() 142 ] 143 144 } 145 146} 147
测试
文件夹的基础文件 我复制的通过vue-cli创建的项目
运行
npm run start

打包
npm run build

拓展
这只是一个简单的项目
我们可以增加插件等赋予它更多能力 还有很多需要优化的地方 比如配置文件可以通过合并来优化
开发环境减少插件使用等等
