1. ホーム
  2. ジャワ

Webpack5ビルド Vue3 + TSプロジェクト

2022-03-23 22:21:18

1. 前書き

2年前に "Webpack4 Build Vue Project" という記事を書きましたが、その後 webpack5 と vue3 がリリースされたので createVue プロジェクトをバージョンアップしたいと思いつつ、時間がないから(実は怠け者だから)先延ばしにしてきました。数日いじった後、ようやくプロジェクト全体をビルドしたので、この記事でアップグレードとビルドの過程を記録しておこうと思う。

追記:実は公式のscaffoldで構築できるのに、なぜゼロから始めるのか?足場なんていらないよ、投げればいいんだから。ね、楽しければいいんです~?

2. 準備

なぜアップグレードするのか?それは、新しいバージョンがもたらす新しい機能を楽しむためです。

Webpack5 の新機能

  • 永続的キャッシュ

  • moduleIds & chunkIds の最適化

  • よりスマートなツリーシェイク

  • モジュールフェデレーション

  • ...

Vue3の新機能

  • 小型化

  • より速く

  • TypeScriptのサポート強化

  • API設計の一貫性強化

  • 自身のメンテナンス性の向上

  • より多くの基本機能を開放する

プロジェクトのテクノロジースタックを定義する

  • プログラミング言語。タイプスクリプト 4.2.4

  • ビルドツールです。[Webpack 5.33.2]()

  • フロントエンドフレームワーク。Vue 3.0.11

  • ルーティングツール。Vue Router 4.0.6

  • 状態管理。Vuex 4.0.0

  • CSSのプリコンパイル。Sass / Less

  • HTTPツール。Axios

  • Gitフックツール。Husky + Lint-staged

  • コードの指定。エディタコンフィグ+Prettier+ESLint

  • コミット仕様です。コミットリント

  • ビルドのデプロイメント。Travis

3. プロジェクトビルド

この記事はゼロからのビルドではなく、[email protected] を改造したビルドなので、わからない人はまず "Webpack4 Build Vue Project" を読んで、ステップバイステップでビルドし、その後この記事を読んでアップグレードするとよいでしょう。

createVueフォルダを作成し、そこに移動し、npm initでプロジェクトを初期化します。

いつものように、webpackの四つ打ちをインストールします。 npm i webpack webpack-cli webpack-dev-server webpack-merge --save-dev

Current version in use.
"webpack": "^5.33.2",
"webpack-bundle-analyzer": "^4.4.1",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.7.3",


webpack5 start development server コマンドは、以前と異なり、以下のように変更されています。  webpack-dev-server  から  webpack serve ということで、package.jsonのスクリプトの先頭を、以下のように変更します。  "start": "webpack serve --progress --hot --inline --config build/webpack.dev.js"

  1. 対応するファイルを作成する

以前と大きな違いはありません。以下の変更点が追加されました。

1). 永続的キャッシュ、キャッシュの設定を追加しました。v5のデフォルトのキャッシュはメモリですが、設定を"ファイルシステム"ハードディスクに書き込むに変更します。

// webpack.dev.js
module.exports = merge(common, {
  cache: {
    type: 'filesystem',
  }
  //...
}


2). プラグイン clean-webpack-plugin (v5 サポート), webpack.HashedModuleIdsPlugin (v5 better moduleIds & chunkIds), HardSourceWebpackPlugin (v5 サポート), hapypack ( v5 非対応) を削除しました。

vue core parsing プラグインをインストールします。

パージングプラグインは  vue-template-compiler  から  @vue/compiler-sfc vue-loader  は変更されません。  npm i vue-loader @vue/compiler-sfc --save-dev

// The current version I'm using
"vue-loader": "^16.2.0",
"@vue/compiler-sfc": "^3.0.11",


vue3および関連ライブラリのインストール、vueタイプファイルの追加

npm i vue@next [email protected] vue-router --save

src フォルダに shims-vue.d.ts ファイルを追加して、vue のタイプエラーを解決します。

// shims-vue.d.ts
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}


htmlテンプレート解析プラグインのインストール

npm i html-webpack-plugin --save-dev

typescriptとパース用プラグインのインストール

npm i typescript ts-loader --save-dev

パースするためのts-loaderを設定します。

// webpack.base.js
// rules
{
    test: /\. (t|j)s$/,
    exclude: /node_modules/,
    use: [
      {
        loader: 'ts-loader',
        options: {
          // Specify a specific ts-compile configuration, in order to distinguish the script's ts configuration
          configFile: path.resolve(__dirname, '. /tsconfig.loader.json'),
          // Add a .ts or .tsx suffix to the corresponding file
          appendTsSuffixTo: [/\.vue$/],
        },
      },
    ],
}


ts-loader は単一のプロセスに対して型チェックと翻訳を行うので、少し遅く、マルチプロセスのソリューションで使用することができます:つまり、ts-loader の型チェックをオフにすると、型チェックは、以下のように実行されます。  fork-ts-checker-webpack-plugin  プラグインを使用します。 npm i fork-ts-checker-webpack-plugin --save-dev

// webpack.base.js
// rules
{
    test: /\. (t|j)s$/,
    exclude: /node_modules/,
    use: [
      {
        loader: 'ts-loader',
        options: {
          // Specify a specific ts-compile configuration, in order to distinguish the script's ts configuration
          configFile: path.resolve(__dirname, '. /tsconfig.loader.json'),
          // Add a .ts or .tsx suffix to the corresponding file
          appendTsSuffixTo: [/\.vue$/],
          transpileOnly: true, // ? Turn off type checking, i.e. only transpile
        },
      },
    ],
}
// plugins push
new ForkTsCheckerWebpackPlugin()



というわけで、プロジェクトは基本的に立ち上がったわけですが、ここで質問です。Tsは指定されたバージョンのjsにコンパイルできるので、やはりbabelは必要なのでしょうか?

tscのターゲットはシンタックスを翻訳するだけで、ポリフィルを統合するわけではないので、やはりバベルが必要です。

例えば、arrow関数を通常の関数に変換したり、aiSnc + awaitをPromise.thenに変換したり、これらは構文変換です。

しかし、実行環境にPromise.prototype.finallyがない場合は、やはりないのです。

だから、私たちのプロジェクトにはまだbabelが必要なのです。

Webpackは既存のTypescriptのソリューションを翻訳します。

パフォーマンスとスケーラビリティを考慮すると、現在の推奨は  babel+fork-ts-checker-webpack-plugin  の解決策になります。

babel7以前は、ts-loaderとbabel-loaderの両方を使用する必要があり、コンパイル時に  TS > TS compiler > JS > Babel > JS  . JSを2回コンパイルするのは、ちょっと効率が悪いことがおわかりいただけると思います。しかし、babel7ではtypescriptをパースする機能が出てきて、そのレベルのサポートがあれば、tsのコンパイル処理をもう一回追加することなく、babelを使えばいいだけなのです。

babel 7 では、新しい  @babel/preset-typescript  プリセットといくつかのプラグインを組み合わせて、ほとんどの ts 構文をパースします。

では、BabelはTypeScriptのコードをどのように扱うのでしょうか?

BabelはすべてのTypeScriptを削除し、通常のJavaScriptに変換し、独自の方法で処理し続けます。TypeScriptを削除することで、型チェックや型エラーのリマインダーがなくなり、コンパイルが速くなり、楽しくプログラミングができるようになります。

もちろん、型安全性のチェックは欠かせないので、スクリプトを追加することでどこかのタイミングで一元化することは可能です。

"check-types": "tsc --watch",


タイプスクリプトをパースするためにバベルを追加する

# Install the following dependencies --save-dev
# webpack loader
babel-loader
# babel core
@babel/core
# Smart conversion to target runtime code
@babel/preset-env
# Parse babel presets for typescript
@babel/preset-typescript
# polyfill 
@babel/plugin-transform-runtime
# support for ts class writing
@babel/plugin-proposal-class-properties 
# Support for three-point expanders
@babel/plugin-proposal-object-rest-spread

# Install the following dependencies --save
@babel/runtime
@babel/runtime-corejs3
"core-js": "^3.11.0",


ts-loader を削除し、babel-loader を追加しました。

{
    test: /\. (t|j)s$/,
    exclude: /node_modules/,
    use: [
      {
        loader: 'babel-loader',
      },
    ],
}


babelの設定ファイルbabel.config.jsをプロジェクトルートに追加します。

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        useBuiltIns: 'usage', // introduce polyfill on demand
        corejs: 3,
      },
    ],
    [
      '@babel/preset-typescript', // reference Typescript plugin
      {
        allExtensions: true, // support all file extensions, otherwise using ts in vue files will report an error
      },
    ],
  ],
  plugins: [
    [
      '@babel/plugin-transform-runtime',
      {
        corejs: 3,
      },
    ],
    '@babel/proposal-class-properties',
    '@babel/proposal-object-rest-spread',
  ],
}


4. コードの指定

プロジェクトのコード仕様は、EditorConfig、Prettier、ESLint、Husky、Lint-stagedを統合し、PrettierとESLintの競合問題をどう解決するか、具体的な実装は、"0から便利で標準化したVue3.xプロジェクトエンジニアリング環境構築"という記事を参照してください、非常に詳しいので改めて紹介しないですけど。

5.コミット仕様

設定されたコミットタイプを選択するためにinquirerを使用し、コミットチェックを実装するためにcommitlintを使用する

npm i inquirer shelljs @commitlint/{cli,config-conventional} -D


package.json用のスクリプトを追加します。

"commitlint": "commitlint -e", 
"commit": "node commit/git-commit.js"


commit/git-commit.js ファイルを作成します。

const shell = require('shelljs')
const inquirer = require('inquirer')
const prompsConfig = {
  ciType: [
    {
      type: 'list',
      name: 'type',
      message: 'Please select the type of this submission:',
      choices: [
        {
          name: 'Introduce new features',
          value: 'feat',
        },
        {
          name: 'Improve the structural formatting/style of the code',
          value: 'style',
        },
        {
          name: 'fix bug',
          value: 'fix',
        },
        {
          name: 'improve performance',
          value: 'perf',
        },
        {
          name: 'delete code or file',
          value: 'delete',
        },
        {
          name: 'Other changes, such as changing the build process, or adding dependencies, tools, etc.',
          value: 'chore',
        },
        {
          name: 'refactor',
          value: 'refactor',
        },
        {
          name: 'write documentation',
          value: 'docs',
        },
        {
          name: 'Add test',
          value: 'test',
        },
        {
          name: 'Update package file',
          value: 'build',
        },
        {
          name: 'Initial commit',
          value: 'init',
        },
        {
          name: 'release/version tag',
          value: 'release',
        },
        {
          name: 'deploy function',
          value: 'deploy',
        },
        {
          name: 'code rollback',
          value: 'revert',
        },
        {
          name: 'CI continuous integration modification',
          value: 'ci',
        },
      ],
    },
  ],
  ciMsg: {
    type: 'input',
    name: 'msg',
    message: 'Please enter the submission text:',
    validate: function (value) {
      if (value) {
        return true
      }
      return 'Text must be entered!'
    },
  },
}

async function gitCommit() {
  let { type } = await inquirer.prompt(prompsConfig.ciType)
  let { msg } = await inquirer.prompt(prompsConfig.ciMsg)

  shell.exec(`git commit -m "${type}: ${msg}"`, function () {
    console.log(`\n commit script: git commit -m "${type}: ${msg}"`)
  })
}

gitCommit()



commitlintの種類を設定するには、commitlint.config.jsファイルを作成します。

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', [
      'build', 'chore', 'ci', 'feat', 'docs', 'fix', 'perf', 'revert', 'refactor', 'style', 'test', 'init', 'build', 'release', 'delete'
     ]],
  }
};


上記の操作が完了すると git add related files を実行します。  npm run commit  コミットチェックサムを実行するために

6. ビルド・デプロイ・Travis CI

Travis CIは、ビルドとテストの自動化ツールで、開発効率を向上させるだけでなく、開発プロセスをより信頼性の高いプロフェッショナルなものにすることで、ソフトウェアの価値を向上させることができます。そして、オープンソースプロジェクトでは無料で使えるので、お金をかけずにいろいろなことをやってくれる。詳しい紹介は、Yifeng Ruan - Continuous Integration Services Travis CI Tutorialをご覧ください。

まず、公式サイトtravis-ci.orgにアクセスし、右上の自分のアバターをクリックし、GithubのアカウントでTravis CIにログインしてください。

対応するリポジトリを探し、スイッチを入れて追加します。

githubのsetting/Developer settings/Personal access tokenでtravisトークンを生成する。

<img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/69ea45bccd674eaeb7023ea850aa2be1~tplv-k3u1fbpfcp-watermark.image" width="700"/>

対応するリポジトリの設定をクリックします

環境変数GITHUB_TOKENに先ほどgithubで生成したトークンを設定する

<img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a1594556dfc3449698070dfb99c18f59~tplv-k3u1fbpfcp-watermark.image" width="700"/>

設定ファイル .travis.yml を作成します。

language: node_js
node_js:
  - 12
branchs:
  only:
    - master
cache:
  directories:
    - node_modules
install:
  - yarn install
scripts:
  - yarn build
deploy:
  provider: pages
  local_dir: dist
  skip_cleanup: true
  # A token generated on GitHub that allows Travis to push code to your repository.
  # Configured in the Travis settings page corresponding to the repository, for security control.
  github_token: $GITHUB_TOKEN
  keep_history: true
  on:
    branch: master


master にプッシュしたり pr が master にマージしたりしたときに、デプロイスクリプトが起動し、結果の dist を gh-pages ブランチにプッシュするようにします。

<img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1710d33f1a1c4da18ad28ef2c4805f34~tplv-k3u1fbpfcp-watermark.image" width="700"/>

7. 問題点とまとめ

  • webpack4よりもビルド時間が長くなっていますが、これはtsの導入とhappypackのマルチプロセスビルドが削除されたため、若干時間がかかるようになったためと思われます

  • devサーバーがポートをインクリメントしない

  • fork-ts-checker-webpack-plugin は、vue の ts 型エラーを検出しません。

長い間これをいじっていて、必ずしも実際のプロジェクトで使えるわけではないのですが、エンジニアリング的なことをたくさん学びました!でもなんだかなぁ。

終了

 シェア、いいね、ウォッチ" ウェーブを応援する