webpack5 を使用して vue 開発環境を手動で構築する

webpack5を使ってvue開発環境を構築する

序文

通常、vue プロジェクトを開発するときは、vue 公式 Web サイトの推奨に従って、次のコマンドを直接実行してプロジェクトを作成します。

npm init vue@latest

このコマンドは、Vue の公式プロジェクト スキャフォールディング ツールである create-vue をインストールして実行します。

ただし、これはこの記事の主題ではありません。この記事では、Webpack 5.0 を使用して Vue 開発環境を構成するプロセスを記録し、プロジェクトの作成プロセスで Vue CLI が行うことについて詳しく説明します。

準備

Webpackの概念の紹介

以前に webpack4 を使用して vue 開発環境を構成したことがある場合は、 webpack4 から webpack5 への移行を確認できます。

環境構成

プロジェクトを初期化する

新しいプロジェクトのルート ディレクトリ フォルダーを作成し、そのフォルダーにプロジェクト名として名前を付けます。フォルダーに入り、次のコマンドを実行します。

npm init -y

ファイルがルート ディレクトリに生成されpackage.json、次のように変更されます。

{
    
    
  "name": "webpack5-vue-template",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    
    },
  "keywords": [],
  "author": "ricky",
  "license": "ISC"
}

Webpackをインストールする

注文の実行:

npm i webpack webpack-cli -D

package.jsonに表示されます:

{
    
    
  "name": "webpack5-vue-template",
  ...
  "devDependencies": {
    
    
    "webpack": "^5.86.0",
    "webpack-cli": "^5.1.4"
  }
}

パッケージング環境を構成する

プロジェクトのルート パスの下に新しいディレクトリを作成しbuild、その中に 3 つの新しいファイルを作成しますjs

  1. webpack.common.jsパブリック環境の構成
  2. webpack.dev.js開発環境の構成
  3. webpack.prod.js本番環境の構成

package.json の script パラメータを変更し、スクリプト実行時にスクリプト内で判断するための環境変数を渡します。

{
    
    
  ...
  "scripts": {
    
    
    "build:dev": "webpack --progress --config ./build/webpack.dev.js",
    "build": "webpack --progress --node-env production --config ./build/webpack.prod.js"
  },
  ...
}

ルート ディレクトリの下に、srcビジネス コードを保存する新しいフォルダーを作成し、その中に新しいフォルダーを作成しますmain.jsassets

assetsディレクトリ内に新しいfontsandディレクトリを作成しますimg

webpack-merge をインストールする

共通の構成を環境固有の構成とマージするには、この依存関係をインストールします。最後に、予想される構成ファイルをエクスポートします

npm i webpack-merge -D

webpack.common.js

const path = require('path');

module.exports = {
    
    
  entry: {
    
    
    main: path.resolve(__dirname, '../src/main.js')
  },
  output: {
    
    
    path: path.resolve(__dirname, '../dist')
  },
}

解決の構成: 頻繁に使用されるファイル パスの一部を省略します

...

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)

distディレクトリにindex.htmlを生成します。

ルート ディレクトリに新しいものを作成します/public/index.htmlindex.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>

プラグインの依存関係をインストールしますhtml-webpack-plugin

npm i html-webpack-plugin -D

HTML テンプレートを次のように設定します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: {
    
    
    ...
  }
}

開発環境を構成する

DevServer ホット アップデート

サーバーの依存関係をインストールし、次のコマンドを実行します。

npm i webpack-dev-server -D

次のプロパティwebpack.dev.jsを構成します。devServer

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

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

...

属性の実行コマンドを次のようにpackage.json設定しますscript

{
    
    
  ...
  "scripts": {
    
    
    "serve": "webpack-dev-server --progress --config ./build/webpack.dev.js",
    ...
  },
  ...
}

バベル言語変換

開発依存関係をインストールします。

npm i babel-loader @babel/core @babel/preset-env -D

本番環境の依存関係をインストールします。

npm i @babel/polyfill core-js

パブリック設定でjs ファイルの読み込みルールwebpack.common.jsを設定します。module.roules

...

module.exports = {
    
    
  ...
  module: {
    
    
    rules: [
      {
    
    
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      }
    ]
  },
  plugins: [
    ...
  ],
  ...
}

プロジェクトのルート ディレクトリに新しいファイルを作成しますbabel.config.js

module.exports = {
    
    
  presets: [
    [
      '@babel/preset-env',
      {
    
    
        useBuiltIns: 'usage',
        corejs: 3
      }
    ]
  ]
}

バベルを使用する前に

ここに画像の説明を挿入

バベルで変身後

[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-TS3fsheg-1686705628388) (C:\Users\liuqi\Documents\Study-code\)アセット\img\1686696819918.png)]

CSS とスタイラス スタイルのパッケージ化

scss 以下にすることもできます。この例ではスタイラスを使用します。最初に依存関係をインストールします。

npm i css-loader style-loader postcss-loader autoprefixer stylus stylus-loader -D

CSS スタイルの変換はパッケージ化時に変換されるため、インストールは開発に依存します。で設定します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: {
    
    
    ...
  }
}

...

ここで使用するのでpostcss、ルート ディレクトリに新しい設定ファイルを作成しますpostcss.config.js

module.exports = {
    
    
  plugins: [
    require('autoprefixer') // 属性根据浏览器不同,自动添加样式前缀
  ]
}

ルート ディレクトリの下に新しいものを作成します.browserslistrc

> 1%
last 2 versions
not dead
not ie 11

最適化:本番環境では、別の CSS スタイル ファイルに抽出され、スタイル コードが圧縮されます。開発環境は必要ありません。

  1. インストールの依存関係:

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

    webpackプラグインのリンク:

    mini-css-extract-plugin

    css-minimizer-webpack-plugin

  2. 構成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: {
          
          
        ...
      }
    }
    
    ...
    
    

フォント、画像、メディアなどの静的リソースのパッケージ化

構成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]'
        }
      }
    ]
  },
  ...
}

rules.Rule.type、つまりリソー​​スモジュールの説明については、公式サイトの説明を参照してください。

vue単体ファイルのパッケージ構成

インストールの依存関係:

  1. ビュー フレームワーク vue をインストールします。npm i vue
  2. ローダー、コンパイラーをインストールします。npm i vue-loader @vue/compiler-sfc -D

構成webpack.common.js:

...
const {
    
     VueLoaderPlugin } = require('vue-loader')
...

module.exports = {
    
    
  ...
  module: {
    
    
    rules: [
      ...
      {
    
    
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      ...
    ]
  },
  plugins: [
    ...
    new VueLoaderPlugin()
  ],
  ...
}

ここまででvueの開発環境が構築できました!


Vue エコシステム機能を統合する

アプリエントリー

srcディレクトリ内に、新しい を作成します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>

srcディレクトリ内に、新しい を作成しますmain.js

import {
    
     createApp } from 'vue'
import App from './App'

const app = createApp(App)

app.mount('#app')

Vue ルーターと Vuex を追加する

本番環境の依存関係をインストールします。

npm i vue-router vuex

srcディレクトリ配下にrouterstoreディレクトリをそれぞれ作成し、順次新しいindex.jsファイルを作成します 具体的な使用方法はvueの公式サイトを参照してください。

ファイルを編集します/router/index.js:

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

注:ここでは のルーティング モードが使用されているhistoryため、webpack.dev.js開発環境で設定する必要があります。

...

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

...

ファイルを編集します/store/index.js:

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

ルーターとストアを 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')

Vue3 でvuex を piniaハイパーリンクに置き換えます

環境変数を定義する

ツリーシェーキングを改善するには、vue3.x プロジェクトに 2 つの変数を設定する必要があります

改訂webpack.common.js

...
const webpack = require('webpack')
...

module.exports = {
    
    
  ...
  plugins: [
    ...
    new webpack.DefinePlugin({
    
    
      __VUE_OPTIONS_API__: true,
      __VUE_PROD_DEVTOOLS__: false
    })
  ],
  ...
}

梱包仕様の設定

パッケージ化時に公開ファイルをコピーする

インストールの依存関係:

npm i copy-webpack-plugin -D

構成では、パッケージ化するときに次のファイルをwebpack.common.jsディレクトリに直接コピーします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
          }
        }
      ]
    })
  ],
  ...
}

ESLint コードの仕様

インストールの依存関係:

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

eslint を実行します。

npx eslint --init

コマンド実行後、プロンプトに従って設定項目を選択します。次に、構成ファイルがプロジェクトのルート ディレクトリに生成されるので.eslintrc.js、ファイルを変更します。

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
  }
}

ルートディレクトリに新しい.eslintconfigファイル.eslintignoreを作成します

  • .editorconfig

    [*.{js,jsx,ts,tsx,vue}]
    indent_style = space
    indent_size = 2
    trim_trailing_whitespace = true
    insert_final_newline = true
    
  • .eslintignore

    /build/
    /dist/
    

Webpack で eslint プラグインを設定する

webpack.common.js 中:

...
const ESLintPlugin = require('eslint-webpack-plugin')
...

module.exports = {
    
    
  ...
  plugins: [
    ...
    new ESLintPlugin({
    
    
      extensions: ['js', 'jsx', 'ts', 'tsx', 'vue']
    })
  ],
  ...
}

パッケージ化する前に、最後にパッケージ化されたコンテンツをクリアします

構成webpack.common.js:

...

module.exports = {
    
    
  ...
  output: {
    
    
    ...
    clean: true
  }
}

ソースマップ

この構成は通常、開発環境でのみ必要となるため、webpack.dev.js次のように構成しますdevtool

...

const devConfig = {
    
    
  mode,
  devtool: 'eval-cheap-module-source-map',
  ...
}

...

パッケージ分析

Webpack のパッケージ化結果の分析はインストールによって異なります。npm i webpack-bundle-analyzer -D

ディレクティブを次のように設定しますpackage.json

{
    
    
  ...
  "scripts": {
    
    
    ...
    "analyze": "webpack --progress --analyze --node-env production --config ./build/webpack.prod.js"
  },
  ...
}

いくつかのヒントをオフにする

運用環境でパッケージ化する場合、大きなファイルに対してパフォーマンスに関するプロンプトが表示される場合がありますが、これは構成によってオフにすることができます。

変更webpack.prod.js:

...

const prodConfig = {
    
    
  ...
  performance: false,
  output: {
    
    
    ...
  }
}

...

他の構成

git が送信されるとき、一部のファイルはコミットされないように無視する必要があります。構成: 次のディレクトリに新しいファイルを作成します.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?

最後に書きます

上記の操作は webpack5 で Vue プロジェクト環境を構築するプロセス全体であり、実際の操作中に webpack の構成に再度慣れます。

この記事の参考文献:

Webpack 5.0 は Vue 開発環境をゼロから構築します

Webpackを手書きしてvue3プロジェクトを作成する手順

おすすめ

転載: blog.csdn.net/qq_44900902/article/details/131200687