Use webpack5 para construir un entorno de desarrollo vue
prefacio
Cuando solemos desarrollar un proyecto vue, solemos ejecutar directamente el siguiente comando para crear un proyecto según la recomendación de la web oficial de vue :
npm init vue@latest
Este comando instalará y ejecutará create-vue, que es la herramienta oficial de andamiaje de proyectos de Vue.
Sin embargo, este no es el tema de este artículo. Este artículo registrará el proceso de uso de Webpack 5.0 para configurar el entorno de desarrollo de Vue y aprenderá más sobre lo que hace la CLI de Vue en el proceso de creación de un proyecto.
Preparar
Introducción al concepto de webpack
Si ha utilizado webpack4 para configurar el entorno de desarrollo de vue anteriormente, puede ver la migración de webpack4 a webpack5
Configuración del entorno
Inicializar el proyecto
Cree una nueva carpeta de directorio raíz del proyecto y asigne a la carpeta el nombre del proyecto. Ingresa a la carpeta y ejecuta el siguiente comando:
npm init -y
Se generará un archivo en el directorio raíz package.json
y se modificará de la siguiente manera:
{
"name": "webpack5-vue-template",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
},
"keywords": [],
"author": "ricky",
"license": "ISC"
}
Instalar paquete web
Ejecutando una orden:
npm i webpack webpack-cli -D
package.json
aparecerá en:
{
"name": "webpack5-vue-template",
...
"devDependencies": {
"webpack": "^5.86.0",
"webpack-cli": "^5.1.4"
}
}
Configurar el entorno de empaquetado
Cree un nuevo directorio en la ruta raíz del proyecto build
y cree tres archivos nuevos en él js
:
webpack.common.js
configuración del entorno públicowebpack.dev.js
Configuración del entorno de desarrollowebpack.prod.js
Configuración del entorno de producción
Modifique el parámetro de secuencias de comandos de package.json y pase las variables de entorno para su evaluación en la secuencia de comandos al ejecutar la secuencia de comandos:
{
...
"scripts": {
"build:dev": "webpack --progress --config ./build/webpack.dev.js",
"build": "webpack --progress --node-env production --config ./build/webpack.prod.js"
},
...
}
En el directorio raíz, cree una nueva src
carpeta: almacene el código comercial y cree una nueva carpeta en él main.js
.assets
assets
fonts
Cree un nuevo directorio y dentro del directorio img
.
Instalar webpack-merge
Instale esta dependencia para fusionar la configuración común con la configuración específica del entorno. Finalmente exporte el archivo de configuración esperado
npm i webpack-merge -D
paquete web.common.js
const path = require('path');
module.exports = {
entry: {
main: path.resolve(__dirname, '../src/main.js')
},
output: {
path: path.resolve(__dirname, '../dist')
},
}
Configurar resolver: omitir algunas rutas de archivos de uso frecuente
...
module.exports = {
entry: {
...
},
resolve: {
alias: {
'@': path.resolve(__dirname, '../src'),
'@img': path.resolve(__dirname, '../src/assets/img')
},
extensions: ['.js', '.vue']
},
...
}
webpack.dev.js
const {
merge } = require('webpack-merge')
const commonConfig = require('./webpack.common')
const mode = process.env.NODE_ENV === 'production' ? 'production' : 'development'
const devConfig = {
mode,
output: {
filename: 'js/[name].js',
chunkFilename: 'js/[name].chunk.js'
}
}
module.exports = merge(commonConfig, devConfig)
webpack.prod.js
const {
merge } = require('webpack-merge')
const commonConfig = require('./webpack.common')
const mode = process.env.NODE_ENV === 'production' ? 'production' : 'development'
const prodConfig = {
mode,
output: {
filename: 'js/[name].[contenthash:8].js',
chunkFilename: 'js/[name].[contenthash:8].chunk.js'
}
}
module.exports = merge(commonConfig, prodConfig)
Generar index.html en el directorio dist
Cree uno nuevo en el directorio raíz /public/index.html
:index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="app"></div>
</body>
</html>
Instale html-webpack-plugin
las dependencias del complemento:
npm i html-webpack-plugin -D
Configure la plantilla html en webpack.common.js
:
...
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html'),
title: 'This is a template'
})
],
output: {
...
}
}
Configurar el entorno de desarrollo
Actualización en caliente de DevServer
Instale las dependencias del servidor, ejecute el comando:
npm i webpack-dev-server -D
webpack.dev.js
Configurar devServer
propiedades en :
const path = require('path')
...
const devConfig = {
...
devServer: {
static: path.resolve(__dirname, '../dist'),
port: 3000,
open: true,
hot: true
},
output: {
...
}
}
...
package.json
Configure el comando de ejecución del atributo en script
:
{
...
"scripts": {
"serve": "webpack-dev-server --progress --config ./build/webpack.dev.js",
...
},
...
}
Conversión de idioma de Babel
Instalar dependencias de desarrollo:
npm i babel-loader @babel/core @babel/preset-env -D
Instalar dependencias de producción:
npm i @babel/polyfill core-js
webpack.common.js
Configure module.roules
las reglas de carga para archivos js en la configuración pública :
...
module.exports = {
...
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
},
plugins: [
...
],
...
}
Cree un nuevo archivo en el directorio raíz del proyecto babel.config.js
:
module.exports = {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: 3
}
]
]
}
Antes de usar babel
Después de transformarse con babel
empaquetado estilo css y stylus
También puede ser scss o menos, este ejemplo usa stylus. Instale las dependencias primero:
npm i css-loader style-loader postcss-loader autoprefixer stylus stylus-loader -D
La conversión de estilo css se convierte al empaquetar, por lo que la instalación es una dependencia de desarrollo. Configurar en webpack.dev.js
:
...
const devConfig = {
...
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
'postcss-loader'
]
},
{
test: /\.styl(us)$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
//启用/禁用或者设置在 css-loader 前应用的 loader 数量
importLoaders: 2
}
},
'postcss-loader',
'stylus-loader'
]
}
]
},
output: {
...
}
}
...
Se utiliza aquí postcss
, así que cree un nuevo archivo de configuración en el directorio raíz postcss.config.js
:
module.exports = {
plugins: [
require('autoprefixer') // 属性根据浏览器不同,自动添加样式前缀
]
}
Cree uno nuevo en el directorio raíz .browserslistrc
:
> 1%
last 2 versions
not dead
not ie 11
Optimización: en el entorno de producción, se extrae en un archivo de estilo css separado y el código de estilo se comprime. No se requiere un entorno de desarrollo.
-
Dependencias de instalación:
npm i mini-css-extract-plugin css-minimizer-webpack-plugin -D
enlace del complemento del paquete web:
-
Configuración
webpack.prod.js
:... const MiniCssExtractPlugin = require('mini-css-extract-plugin') const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') ... const prodConfig = { ... module: { rules: [ { test: /\.css$/, use: [ // 压缩css文件,需配置的loader MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader' ] }, { test: /\.styl(us)$/, use: [ // 压缩css文件,需配置的loader MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { importLoaders: 2 } }, 'postcss-loader', 'stylus-loader' ] } ] }, optimization: { minimizer: [ // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释 // `...`, new CssMinimizerPlugin(), // 这将仅在生产环境开启 CSS 优化。 // 如果还想在开发环境下启用 CSS 优化,请将 optimization.minimize 设置为 true: ] }, plugins: [ new MiniCssExtractPlugin({ // 决定输出的每个 CSS 文件的名称 filename: 'css/[name].[contenthash:8].css', // 决定非入口的 chunk 文件名称,仅在 webpack@5 下可用 chunkFilename: 'css/[name].[contenthash:8].chunk.css' }) ], output: { ... } } ...
Empaquetado de recursos estáticos como fuentes, imágenes y medios.
Configuración webpack.common.js
:
...
const isProduction = process.env.NODE_ENV === 'production'
module.exports = {
...
module: {
rules: [
...
{
test: /\.(ttf|woff|woff2|eto|svg)$/,
exclude: path.resolve(__dirname, '../src/assets/img'),
type: 'asset',
parser: {
dataUrlCondition: {
//如果一个模块源码大小小于 maxSize,那么模块会被作为一个 Base64 编码的字符串注入到包中, 否则模块文件会被生成到输出的目标目录中。
maxSize: 4 * 1024 // 4kb
}
},
generator: {
filename: isProduction
? 'static/fonts/[name].[contenthash:8][ext]'
: 'static/fonts/[name][ext]'
}
},
{
test: /\.(jpe?g|png|gif|svg)$/,
exclude: path.resolve(__dirname, '../src/assets/fonts'),
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 4 * 1024
}
},
generator: {
filename: isProduction ?
'static/img/[name].[contenthash:8][ext]' :
'static/img/[name][ext]'
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)$/,
type: 'asset/resource',
generator: {
filename: isProduction ?
'static/video/[name].[contenthash:8][ext]' :
'static/video/[name][ext]'
}
}
]
},
...
}
Para obtener una descripción de rules.Rule.type, es decir, el módulo de recursos, consulte la descripción del sitio web oficial para obtener más información.
Configuración de empaquetado vue archivo único
Dependencias de instalación:
- Instale el marco de vista vue:
npm i vue
- Instalar cargador, compilador:
npm i vue-loader @vue/compiler-sfc -D
Configuración webpack.common.js
:
...
const {
VueLoaderPlugin } = require('vue-loader')
...
module.exports = {
...
module: {
rules: [
...
{
test: /\.vue$/,
loader: 'vue-loader'
},
...
]
},
plugins: [
...
new VueLoaderPlugin()
],
...
}
¡Hasta ahora, se ha construido el entorno de desarrollo vue!
Integrar la función del ecosistema Vue
entrada de la aplicación
En src
el directorio, crea un nuevo App.vue
:
<template>
<div class="app">{
{ msg }}</div>
</template>
<script>
export default {
name: 'App',
data () {
return {
msg: 'Hello world'
}
}
}
</script>
<style lang="stylus" scoped>
.app
color: skyblue
</style>
En src
el directorio, crea un nuevo main.js
:
import {
createApp } from 'vue'
import App from './App'
const app = createApp(App)
app.mount('#app')
Agregar enrutador Vue y Vuex
Instalar dependencias de producción:
npm i vue-router vuex
En src
el directorio, cree router
y store
directorio respectivamente, y luego cree nuevos index.js
archivos a su vez. Para conocer los métodos de uso específicos, consulte el sitio web oficial de vue.
editar /router/index.js
archivo:
import {
createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// 懒加载。webpackChunkName 指定chunkname为 about
component: () => import(/* webpackChunkName: "about" */ '@/views/About')
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
Nota: El modo de enrutamiento de se usa aquí history
, por lo que debe webpack.dev.js
configurarse en el entorno de desarrollo:
...
const devConfig = {
...
devServer: {
...
// 配置history路由模式
historyApiFallback: true
},
...
}
...
Editar /store/index.js
archivo:
import {
createStore } from 'vuex'
const store = createStore({
state: {
count: 1
},
actions: {
add ({
commit }) {
commit('add')
}
},
mutations: {
add (state) {
state.count++
}
},
getters: {
getCount (state) {
return state.count
}
}
})
export default store
Agregue el enrutador y la tienda a main.js:
import {
createApp } from 'vue'
import App from './App'
import router from './router'
import store from './store'
const app = createApp(App)
app.use(router).use(store).mount('#app')
Reemplace vuex con el hipervínculo pinia en Vue3
Definir variables de entorno
Se deben configurar dos variables en el proyecto vue3.x para una mejor sacudida del árbol
Revisarwebpack.common.js
...
const webpack = require('webpack')
...
module.exports = {
...
plugins: [
...
new webpack.DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false
})
],
...
}
Configurar especificaciones de embalaje
Copie archivos públicos al empaquetar
Dependencias de instalación:
npm i copy-webpack-plugin -D
Configuración , copie los siguientes archivos webpack.common.js
directamente en el directorio al empaquetar :public
dist
...
const CopyPlugin = require('copy-webpack-plugin')
...
module.exports = {
...
plugins: [
...
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, '../public'),
to: path.resolve(__dirname, '../dist'),
filter: (resourcePath) => {
if (resourcePath.includes('/public/index.html')) {
return false
}
return true
}
}
]
})
],
...
}
Especificación del código ESLint
Dependencias de instalación:
npm i eslint eslint-webpack-plugin @babel/eslint-parser -D
npm i eslint-config-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-n -D
npm i eslint-plugin-vue -D
Ejecutar eslint:
npx eslint --init
Después de ejecutar el comando, seleccione el elemento de configuración de acuerdo con el aviso. Luego se generará un archivo de configuración en el directorio raíz del proyecto .eslintrc.js
, modifique el archivo:
module.exports = {
root: true,
env: {
browser: true,
es2021: true
},
extends: [
'plugin:vue/vue3-essential',
'standard'
],
parserOptions: {
parser: '@babel/eslint-parser'
},
plugins: [
'vue'
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'vue/multi-word-component-names': 0
}
}
Crear un nuevo archivo .eslintconfig
y en el directorio raíz.eslintignore
-
.editorconfig
[*.{js,jsx,ts,tsx,vue}] indent_style = space indent_size = 2 trim_trailing_whitespace = true insert_final_newline = true
-
.eslintignore
/build/ /dist/
Configurar el complemento eslint en el paquete web
En webpack.common.js:
...
const ESLintPlugin = require('eslint-webpack-plugin')
...
module.exports = {
...
plugins: [
...
new ESLintPlugin({
extensions: ['js', 'jsx', 'ts', 'tsx', 'vue']
})
],
...
}
Borrar el último contenido empaquetado antes del embalaje
Configuración webpack.common.js
:
...
module.exports = {
...
output: {
...
clean: true
}
}
FuenteMapa
Esta configuración generalmente solo se requiere en el entorno de desarrollo, así que webpack.dev.js
configúrela en devtool
:
...
const devConfig = {
mode,
devtool: 'eval-cheap-module-source-map',
...
}
...
análisis de paquetes
El análisis de resultados del paquete webpack depende de la instalación:npm i webpack-bundle-analyzer -D
Configurar directivas en package.json
:
{
...
"scripts": {
...
"analyze": "webpack --progress --analyze --node-env production --config ./build/webpack.prod.js"
},
...
}
desactivar algunas pistas
Al empaquetar en el entorno de producción, puede haber algunas indicaciones de rendimiento para archivos grandes, que se pueden desactivar mediante la configuración:
modificar webpack.prod.js
:
...
const prodConfig = {
...
performance: false,
output: {
...
}
}
...
alguna otra configuración
Cuando git envía, algunos archivos deben ignorarse para que no se confirmen. Configuración: Cree un nuevo archivo en el siguiente directorio .gitignore
:
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
escribir al final
Las operaciones anteriores son todo el proceso de creación del entorno del proyecto Vue con webpack5, y está familiarizado con la configuración de webpack nuevamente durante la operación real.
Referencias en este artículo:
Webpack 5.0 crea un entorno de desarrollo Vue desde cero
El proceso de creación de un proyecto vue3 mediante el paquete web de escritura a mano