1. Introduction

Two years ago, I wrote an article called “Build a Vue Project for Webpack4”. Since the release of Webpack5 and Vue3, I have been trying to upgrade my CreateVue project, but I don’t have the time (actually because of laziness) to do so. After a few days of fidgeting, the entire project was finally set up, so this is the only post to document the process.

PS: Why do you have to build it from scratch when it could have been built with official scaffolding?

I don’t use scaffolding when there’s one. Hey, just play ~😄

2. Preparation

Why upgrade? Apart from messing around, it’s about enjoying the new features that the new version brings us.

New features for Webpack5

  • Persistent caching
  • Optimization of Moduleids & Chunkids
  • A more intelligent tree shaking
  • Module Federation
  • .

New features for VUE3

  • smaller
  • faster
  • Enhanced TypeScript support
  • Enforce consistency in API design
  • Improve its maintainability
  • Open up more underlying functionality

Determine the project technology stack

  • Programming language: TypeScript 4.2.4
  • Build tool: [Webpack 5.33.2]()
  • Front-end framework: Vue 3.0.11
  • Routing tool: Vue Router 4.0.6
  • State management: Vuex 4.0.0
  • CSS precompiled: Sass/Less
  • HTTP tool: Axios
  • Git Hook Tool: Husky + Lint-Passage
  • Code specification: editorConfig + Prettier + ESLint
  • Commitlint: Commitlint
  • Build the deployment: Travis

3. Project construction

This article is not built from zero, but from
[email protected] the basis of modification to build, if you do not understand, you can see first
“Webpack4 Vue Construction Project”, follow step by step to build, and then see this article to upgrade

  1. Create the createVue folder, enter the folder, and initialize the project with NPM init
  2. NPM I webpack webpack-cli webpack-dev-server webpack-merge –save-dev

    Currently using version: "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",

    The webpack5 start development server command has changed from webpack-dev-server to webpack serve, so the script start in package.json is changed to: “start”: “webpack serve –progress –hot –inline –config build/webpack.dev.js”

  3. Create the appropriate file

Not much different than before. There are several points that add to the changes:

1). Persistent cache, add cache configuration. V5 cache default is memory, change the Settings “filesystem” to disk

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

2). Remove the plugin clean – webpack – plugin (v5), webpack. HashedModuleIdsPlugin better moduleIds & chunkIds (v5), HardSourceWebpackPlugin (V5 supported), HappyPack (V5 not compatible)

  1. Install the Vue core parsing plug-in

The parsing plugin is different, changing from vue-template-compiler to @vue/compiler-sfc, with the vue-loader remaining the same. npm i vue-loader @vue/compiler-sfc –save-dev

/ / current version I use "vue - loader" : "^ 16.2.0", "@ vue/compiler - SFC" : "^ 3.0.11",
  1. Install VUE3 and related libraries and add VUE type files

NPM I vue@next call vue-router --save

Add shims-vue.d.ts file to SRC folder to resolve Vue type error

// shims-vue.d.ts
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}
  1. Install the HTML template parsing plug-in

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

  1. Install TypeScript and the parsing plug-in

npm i typescript ts-loader --save-dev

Configure TS-Loader:

// webpack.base.js // rules { test: /\.(t|j)s$/, exclude: /node_modules/, use: [ { loader: 'ts-loader', options: {// Specify the TS compilation configuration in order to distinguish the script's TS configuration configFile: Path. The resolve (__dirname, '.. / tsconfig. Loader. Json '), / / add a corresponding file. Ts or. TSX suffix appendTsSuffixTo: / / \. Vue $/,,}},],}

TS-Loader performs type checking and translation for a single process, so it is a bit slow. A multi-process solution can be used: that is, type checking is turned off by TS-Loader, and type checking is performed by 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 the TS compilation configuration in order to distinguish the script's TS configuration configFile: Path. Resolve (__dirname, '../tsconfig.loader.json'), // Add a.ts or.tsx suffixto: [/\.vue$/], transpileOnly: True, / /? Closed type checking, that is, only translated},},]} / / plugins push new ForkTsCheckerWebpackPlugin ()

At this point, the project is almost ready to run, so there is a question: TS can be compiled to the specified version of JS, so do you still need Babel?

TSC’s Target only interprets syntax and does not integrate polyfill, so Babel is still needed.

For example, turning the arrow function into normal function, and aysnc + await into promise.then is syntax translation;

If there is no Promise. But you run surroundings prototype. Finally, then no or not.

So we still need Babel in the project.

Webpack translation of TypeScript

plan 1 2 3
Single-process scenario (type checking and translation in the same process) Ts – loader (transpileOnly to false) awesome-typescript-loader
Multiprocess scheme TS-loader (transpileOnly true) + fork-ts-checker-webpack-plugin Awesome – TypeScript-Loader + CheckerPlugin babel + fork-ts-checker-webpack-plugin

Considering performance and scalability, Babel +fork-ts-checker-webpack-plugin is recommended at present.

Before Babel 7, it was necessary to use both TS-loader and Babel -loader, and the compilation procedure was TS >, TS compiler > JS > Babel > JS. It can be seen that after compiling js twice, the efficiency is a little low. But with Babel 7 coming out with the ability to parse TypeScript, with this layer of support, we could just use Babel without having to go through another TS build.

In Babel 7, we used the new @babel/ preset-TypeScript preset and a few plugins to parse most of the TS syntax.

So, how does Babel handle TypeScript code?

Babel removes all TypeScript, converts it to regular JavaScript, and continues to process it its own way. Removing TypeScript eliminates the need for type checking and annoying type error alerts, so compile faster and program happily 😄

Of course, type-safety checking is essential, so we can do it all at one time and add script:

"check-types": "tsc --watch",
  1. Add Babel to parse TypeScript
# install the following dependencies --save-dev # webpack loader Babel -loader # Babel core @babel/core # intelligently convert to target runtime code @babel/preset-env # parse TypeScript's Babel preset @babel/preset-typescript # polyfill @babel/plugin-transform-runtime # supports TS class writing @babel/plugin-proposal-class-properties # Support three-point expansion @babel/plugin-proposal-object-rest-spread # Install the following dependencies --save @ Babel/runtime @ Babel/runtime - corejs3 "core - js" : "^ 3.11.0",

Remove TS-Loader and add Babel-Loader

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

Add the Babel configuration file babel.config.js to the project root

Module. exports = {presets: [['@babel/preset-env', {useBuiltIns: 'usage', // Exports = {presets: [['@babel/preset-env', {useBuiltIns: 'usage', // Exports = {presets: [['@babel/preset-env',} 3,},], ['@babel/ preset-TypeScript ', // reference TypeScript plugins {allExtensions: },],], plugins: [['@babel/plugin-transform-runtime', {corejs: 3, }, ], '@babel/proposal-class-properties', '@babel/proposal-object-rest-spread', ], }

4. Code specifications

EditorConf, Prettier, ESLint, Husky, Lint-Lint, Prettier, Prettier, and ESLint are integrated into the code specification of the project, and how to resolve the conflict between Prettier and ESLint The specific implementation can refer to the article “Starting from 0 to build a set of standard Vue3. X project engineering environment”, which is very detailed and will not be described here.

5. Submit specifications

Use Inquirer to select the configured commit type, and implement a commit check with COMMITLint

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

Add package.json to script:

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

Create a commit/git-commit.js file

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 feature ', value: 'feat',}, {name: 'to improve the structure of the code format/style, value:' style '}, {name: 'bug fixes, value:' fix '}, {name: 'performance, value:' perf,}, {name: 'delete code or file ', value: 'delete',}, {name: 'other changes, such as changing the build process, or adding dependent libraries, tools, etc. ', value: 'chore',}, {name:' refactoring ', value: 'refactor,}, {name:' documentation 'value:' docs'}, {name: 'increase test, value:' test '}, {name: 'update package file, the value: 'build'}, {name: 'first submitted, and the value:' init '}, {name: '/ version label, value:' release '}, {name: 'deployment capabilities, value: 'the deploy'}, {name: 'code rollback, value:' revert,}, {name: 'CI CI modification, value:' CI '},],},], ciMsg: {type: Validate: function (value) {if (value) {return true} return ' '}}, } async function gitCommit() { let { type } = await inquirer.prompt(prompsConfig.ciType) let { msg } = await Prompt (prompsconfig.cimsg) shell. Exec (' git commit-m "${type}: ${MSG}" ', function () {console.log(' \n) git commit -m "${type}: ${msg}"`) }) } gitCommit()

Configure the type commitlint and create the file 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'
     ]],
  }
};

When you have done this, you can add git files and execute NPM run commit to perform the commit check

6. Build and deploy Travis CI

Travis CI is an automated build and test tool that not only increases efficiency, but also increases the value of software by making the development process more reliable and professional. Also, it’s free for open source projects and can do a lot of things for you at no cost. For more information, please check out Ruan Yifeng’s Travis CI tutorial for continuous integration services.

First, visit the official website travis-ci.org, click on your profile picture in the top right corner, and use your GitHub account to log in to Travis CI.

Find the corresponding warehouse, open the switch to add the warehouse

Set /Developer Settings /Personal Access Token Create Travis Token on GitHub

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

Click the setting of the corresponding warehouse

Set the environment variable GITHUB_TOKEN to the token generated at GITHUB

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

Create the.travis.yml configuration file:

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. # Construct the Travis Settings page of the repository for security control. github_token: $GITHUB_TOKEN keep_history: true on: branch: master

This way, when you push to the master or merge PR to the master, the deployment script will be triggered to push the generated dist to the GH-Pages branch

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

7. Existing problems and summary

  • The build time was longer than Webpack4, probably due to the introduction of TS and the removal of the HappyPack multi-process build, which took slightly longer
  • The dev server does not increment the port
  • Fork-ts-checker-webpack-plugin cannot detect TS type errors in Vue

I have been tinkering for a long time, and I have learned a lot about engineering. Although it may not be applicable to the actual project, I still have gained something.

8. More recommendations

Canvas Advanced (I) Generation of two-dimensional code and code scanning recognition

Write an NPM plugin that generates a QR code with the logo

Canvas Advanced (3) TS + Canvas rewrite “color discrimination” minigame

Canvas Progression (4) Implements a “Scratch” game

Canvas progression (V) Realize the image filter effect

Canvas Advanced (VI) Realizes the image compression function

VUI create log (I) – picture lazy load instruction implementation

VUI creation log (2) — the implementation of anti-jiggling throttling component

Topic analysis of front-end algorithm (1)

Topic analysis of front-end algorithm (2)

Simple routing implementation — (hash routing)

Simple routing implementation — (History routing)