webpack5构建vue
必要环境
安装ndejs
我们需要安装node 如果没有安装则安装 安装过则跳过
执行
node -v
npm -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可以将我们的代码向下适配
npm i babel-loader @babel/core @babel/preset-env @babel/polyfill core-js@3 -D
安装 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
项目依赖 (面还有需要安装的)
"devDependencies": {
"@babel/core": "^7.16.12",
"@babel/polyfill": "^7.12.1",
"@babel/preset-env": "^7.16.11",
"@element-plus/icons": "^0.0.11",
"@vue/cli-plugin-babel": "^4.5.15",
"@vue/compiler-sfc": "^3.2.29",
"autoprefixer": "^10.4.2",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.3",
"copy-webpack-plugin": "^10.2.1",
"core-js": "^3.20.3",
"css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.4.1",
"element-plus": "^1.3.0-beta.9",
"eslint": "^7.32.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-vue": "^8.4.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.5.0",
"less-loader": "^10.2.0",
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^2.5.3",
"postcss-loader": "^6.2.1",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"style-loader": "^3.3.1",
"terser-webpack-plugin": "^5.3.0",
"unplugin-auto-import": "^0.5.11",
"unplugin-vue-components": "^0.17.15",
"url-loader": "^4.1.1",
"vue": "^3.2.29",
"vue-loader": "^16.1.0",
"vue-router": "^4.0.12",
"vue-style-loader": "^4.1.3",
"vuex": "^4.0.2",
"webpack": "^5.67.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.3"
}
创建多个目录
创建多个文件夹 方便存放不同资源 参考vue-cli脚手架生成的
根目录下新建 webpack.config.js
src下创建main.ts 以及 App.vue
如下
public 目录下
我们放入一个ico文件
创建模板 html文件
webpack5内置了clean output开启即可
在 public目录下新建 index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong><%= htmlWebpackPlugin.options.title %>:请检查js是否正常启用</strong>
</noscript>
<div id="app"></div>
</body>
</html>
开始构建vue项目
安装 vue-loader等
npm i vue-loader vue-template-compiler vue@next vuex@next vue-router@next -D
npm install terser-webpack-plugin copy-webpack-plugin -D
配置webpack
webpack5内置了 clean 和 热更新
开启方式 在devServer配置
devServer: {
hot: true,
liveReload: true
},
在 webpack.config.js 文件中
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const MiniCssExtract = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') //生产环境
const TerserPlugin = require('terser-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = (env) => {
return {
devServer: {
port: 8888,
hot: true,
liveReload: true
},
mode: env.development ? 'development' : 'production',
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
},
entry: './src/main.js',
output: {
filename: "js/[name].[contenthash].js",
// path: path.resolve(__dirname, 'dist/js'),
clean: true,
publicPath: "./"
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
exclude: file => (
/node_modules/.test(file) &&
!/\.vue\.js/.test(file)
),
use: [
{
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
targets: [
'last 1 version', //浏览器最新的一个版本
'> 1%' //代码使用超过1%
],
useBuiltIns: 'usage',
corejs: 3
}
]
]
}
},
{
loader: "eslint-loader"
}
]
},
{
test: /\.(css|scss)$/,
use: [env.development ? 'vue-style-loader'
: MiniCssExtract.loader,
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
}
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource'
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: "file-loader",
options: {
name:'img/[name].[hash].[ext]',
}
}
]
}
]
},
optimization: {
minimizer: [
new CssMinimizerPlugin(),
new TerserPlugin()
]
},
plugins: [
new HtmlWebpackPlugin({
title: "小型vue应用",
template: "public/index.html",
filename: "index.html",
baseUrl: './icon/favicon.ico'
}),
new CopyWebpackPlugin({
patterns:[
{
from: path.resolve(__dirname, './public/icon'),
to: path.resolve(__dirname, './dist/icon'),
}
]
}),
new MiniCssExtract({
filename: 'css/style.css'
}),
new VueLoaderPlugin()
]
}
}
修改package.json
初始化 eslint
eslint --init
选择 检查找到问题
选择 js 浏览器环境 不用ts
拆分配置文件
开发环境
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
devServer: {
port: 8888,
hot: true,
liveReload: true
},
mode: 'development',
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
},
entry: './src/main.js',
output: {
filename: "js/[name].[contenthash].js",
// path: path.resolve(__dirname, 'dist/js'),
publicPath: "/"
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
exclude: file => (
/node_modules/.test(file) &&
!/\.vue\.js/.test(file)
),
use: [
{
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
targets: [
'last 1 version', //浏览器最新的一个版本
'> 1%' //代码使用超过1%
],
useBuiltIns: 'usage',
corejs: 3
}
]
]
}
},
{
loader: "eslint-loader"
}
]
},
{
test: /\.(css|scss)$/,
use: ['vue-style-loader',
{
loader: 'css-loader'
// ,
// options: {
// modules:{
// localIdentName: '[local]_[hash:base64:8]'
// }
// }
},
{
loader: 'sass-loader'
// options: {
// // sass-loader version >= 8
// sassOptions: {
// indentedSyntax: true
// }
// }
}
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource'
},
{
test: /\.(png|jpg|gif)$/,
use: [
// {
// loader:'url-loader',
// options:{
// limit:4096,
// outputPath:'./img',
// name:'[name].[hash].[ext]',
// }
// },
{
loader: "file-loader",
options: {
name:'img/[name].[hash].[ext]',
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: "小型vue应用",
template: "public/index.html",
}),
new VueLoaderPlugin()
]
}
生产环境
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const MiniCssExtract = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') //生产环境
const TerserPlugin = require('terser-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = () => {
return {
mode: 'production',
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
},
entry: './src/main.js',
output: {
filename: "js/[name].[contenthash].js",
// path: path.resolve(__dirname, 'dist/js'),
clean: true,
publicPath: "./"
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
exclude: file => (
/node_modules/.test(file) &&
!/\.vue\.js/.test(file)
),
use: [
{
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
targets: [
'last 1 version', //浏览器最新的一个版本
'> 1%' //代码使用超过1%
],
useBuiltIns: 'usage',
corejs: 3
}
]
]
}
},
{
loader: "eslint-loader"
}
]
},
{
test: /\.(css|scss)$/,
use: [ MiniCssExtract.loader,
{
loader: 'css-loader'
// ,
// options: {
// modules:{
// localIdentName: '[local]_[hash:base64:8]'
// }
// }
},
{
loader: 'sass-loader'
// options: {
// // sass-loader version >= 8
// sassOptions: {
// indentedSyntax: true
// }
// }
}
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource'
},
{
test: /\.(png|jpg|gif)$/,
use: [
// {
// loader:'url-loader',
// options:{
// limit:4096,
// outputPath:'./img',
// name:'[name].[hash].[ext]',
// }
// },
{
loader: "file-loader",
options: {
name:'img/[name].[hash].[ext]',
}
}
]
}
]
},
optimization: {
minimizer: [
new CssMinimizerPlugin(),
new TerserPlugin()
]
},
plugins: [
new HtmlWebpackPlugin({
title: "小型vue应用",
template: "public/index.html",
filename: "index.html",
baseUrl: './icon/favicon.ico'
}),
new CopyWebpackPlugin({
patterns:[
{
from: path.resolve(__dirname, './public/icon'),
to: path.resolve(__dirname, './dist/icon'),
}
]
}),
new MiniCssExtract({
filename: 'css/style.css'
}),
new VueLoaderPlugin()
]
}
}
测试
文件夹的基础文件 我复制的通过vue-cli创建的项目
运行 npm run start
打包 npm run build
拓展
这只是一个简单的项目
我们可以增加插件等赋予它更多能力 还有很多需要优化的地方 比如配置文件可以通过合并来优化
开发环境减少插件使用等等