Use webpack5 para construir manualmente un entorno de desarrollo vue

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.jsony 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.jsonaparecerá 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 buildy cree tres archivos nuevos en él js:

  1. webpack.common.jsconfiguración del entorno público
  2. webpack.dev.jsConfiguración del entorno de desarrollo
  3. webpack.prod.jsConfiguració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 srccarpeta: almacene el código comercial y cree una nueva carpeta en él main.js.assets

assetsfontsCree 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-pluginlas 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.jsConfigurar devServerpropiedades en :

const path = require('path')
...

const devConfig = {
    
    
  ...
  devServer: {
    
    
    static: path.resolve(__dirname, '../dist'),
    port: 3000,
    open: true,
    hot: true
  },
  output: {
    
    
    ...
  }
}

...

package.jsonConfigure 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.jsConfigure module.rouleslas 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

inserte la descripción de la imagen aquí

Después de transformarse con babel

[Error en la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-leeching, se recomienda guardar la imagen y cargarla directamente (img-TS3fsheg-1686705628388) (C:\Users\liuqi\Documents\Study-code\ activos\img\1686696819918. png)]

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.

  1. Dependencias de instalación:

    npm i mini-css-extract-plugin css-minimizer-webpack-plugin -D
    
    

    enlace del complemento del paquete web:

    mini-css-extraer-plugin

    css-minimizer-webpack-complemento

  2. 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:

  1. Instale el marco de vista vue:npm i vue
  2. 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 srcel 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 srcel 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 srcel directorio, cree routery storedirectorio respectivamente, y luego cree nuevos index.jsarchivos a su vez. Para conocer los métodos de uso específicos, consulte el sitio web oficial de vue.

editar /router/index.jsarchivo:

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.jsconfigurarse en el entorno de desarrollo:

...

const devConfig = {
    
    
  ...
  devServer: {
    
    
    ...
    // 配置history路由模式
    historyApiFallback: true
  },
  ...
}

...

Editar /store/index.jsarchivo:

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.jsdirectamente en el directorio al empaquetar :publicdist

...
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 .eslintconfigy 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.jsconfigú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

Supongo que te gusta

Origin blog.csdn.net/qq_44900902/article/details/131200687
Recomendado
Clasificación