[basics] webpack5 build vue3 + typescript basic development environment

Time:2021-10-16

[basics] webpack5 build vue3 + typescript basic development environment

preface

Recently, we upgraded the company’s ancient projects and found that the performance of webpack5 has been greatly improved. In addition to the use of vue3, we specially tried to build a vue3 development environment from scratch without using the official scaffold, mainly to deepen our understanding of this set of technology

Warehouse address

preparation

Step 1: create project directory and initialize

mkdir wp5-vue3
cd wp5-vue3
npm init -y

Step 2: install webpack

npm i webpack webpack-cli -D

Global installation is not selected here. You can choose according to your actual situation

Step 3: create the entry directory SRC and the entry file index.js

mkdir src
touch src/index.js

Just write something

// index.js
console.log('hello webpack5')

Those who have used webpack should know fourCore concept

  • Entry
  • Output
  • loader
  • Plugins

andwebpackdefaultentryIt is Src / index.js in the root directory

Through various methods before outputloaderandpluginsProcessing files

Final output tooutputSpecified folderThe default is the dist folder under the root directory

So here is basically a basic look of webpack. Simple packaging can be realized by inputting webpack from the command line

[basics] webpack5 build vue3 + typescript basic development environment

[basics] webpack5 build vue3 + typescript basic development environment

Step 4: declare the configuration file

Although officials claim that starting with webpack v4.0.0, there is no need to introduce a configuration file. However, you still need to customize the configuration, modify some default configurations or handle the project with some loaders and plugins, so we declare webpack.config.js in the project root directory,The habitually named file name is not mandatory. Specify the configuration file path through — config

/*
 * @Description: webpack.config.js
 * @Author: justX
 * @LastEditors: justX
 * @Date: 2021-07-28 16:15:10
 * @LastEditTime: 2021-07-28 16:20:59
 * @FilePath: /wp5-vue3/webpack.config.js
 */
const path = require('path');

module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist')
    }
}

[basics] webpack5 build vue3 + typescript basic development environment

Modify package.json and add scripts field

"scripts": {
  "Build": "webpack -- config configuration file path"
}

Basic configuration

Don’t worry about completing the basic configuration. Let’s enrich the configuration to make the whole scaffold more useful, such as automatic insertion of HTML files into packaged files in daily development, real-time preview of local services, ES6 + syntax conversion and the use of Vue / less / sass. Next, we will improve them one by one

Create HTML template file

Through the webpack plug-inhtml-webpack-pluginAutomatically insert the packaged JS into the HTML template

1. Installation dependency

npm i html-webpack-plugin -D

2. Modify the configuration

plugins: [
  new HtmlWebpackPlugin({
    template: './index.html',
    filename: 'index.html',
    title: 'webpack5-vue3'
  })
]

Then NPM run build viewdistUnder directoryindex.html, the packaged file has been automatically imported. We view the file in the browser, the page displays normally, and the console outputs normally. However, we can’t bear to refresh it manually every time we modify it! So let’s solve this problem

Local service devserver

Through the webpack plug-inwebpack-dev-serverImplement local development server

1. Installation dependency

npm i webpack-dev-server -D

2. Modify the configuration

module.exports = {
  //...
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000,
  },
};

3. Modify package.json, add scripts, and call webpack dev server through cli

 "scripts": {
    "serve": "npx webpack serve",
    "build": "npx webpack --config webpack.config.js"
  }
  • Note: the webpack 5 startup development server is different from the previous version, from webpack dev server to webpack serve

Then NPM run serve can see that the terminal outputs the address of the local service. Click to access

[basics] webpack5 build vue3 + typescript basic development environment

Now let’s modify the code content of index.js to see if it will refresh automatically

//ES6 arrow function
let arrowFn = () => {
  console.log('es6: arrow function')
};
arrowFn();

//ES7 array includes
console.log('es7:', [1,2,3].includes(1))

//Es8 object entries
let obj = {a: 1, b: 2, c: 3};
Object.entries(obj).forEach(([key, value]) =>{
  console.log('es8', key + ": " + value); //  Output a: 1, B: 2, C: 3
})

However, when we run the above code on these old browsers, we will find that JS reports an error and cannot run. Next, we will convert ECMAScript 2015 + code into JavaScript backward compatible code

ES6 + syntax conversion

Install the Babel core, the corresponding loader and the preset environment

1. Installation dependency

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

2. Modify the configuration

module.exports = {
// ...
  module: {
    rules: [
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }
}

We can write about the configuration of Babel inoptionsThere can also be a separate file in theReference documents

Style processing

The preprocessor used in the project is less

Related dependencies style loader CSS loader less less less loader

1. Installation dependency

npm i  style-loader css-loader less less-loader -D

2. Modify the configuration

module.exports = {
// ...
  module: {
    rules: [
      // ...
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader',
            options: {}
          },
          {
            loader: 'css-loader',
            options: {}
          }
        ]
      },
      {
        test: /\.less$/,
        use: [
          {
            loader: 'style-loader',
            options: {}
          },
          {
            loader: 'css-loader',
            options: {}
          },
          {
            loader: 'less-loader',
            options: {}
          }
        ]
      }
    ]
  }
}

Tips: the loading order of multiple loaders is from bottom to top and from left to right, so the order here must not be wrong~

So far, we have processed the three front-end HTML JS CSS and completed the basic conditions for the composition of a web page, but these are far from enough. Next, we continue to improve the configuration of static resources / vue3 / TS / code specification / multi environment

Static resources (pictures, fonts, audio, etc.)

Asset module is a module type that allows the use of resource files (fonts, icons, etc.) without configuring additional loaders.

Before webpack 5, the following is usually used:

The resource module type replaces all these loaders by adding four new module types:

  • asset/resourceSend a separate file and export the URL. Previously by usingfile-loaderrealization.
  • asset/inlineExport the data URI of a resource. Previously by usingurl-loaderrealization.
  • asset/sourceExport the source code of the resource. Previously by usingraw-loaderrealization.
  • assetAutomatic selection between exporting a data URI and sending a separate file. Previously by usingurl-loaderAnd configure the resource volume limit.

1. Two ways to customize the output file name

//By default, the asset / resource module is sent to the output directory with the [hash] [ext] [query] file name.
//There are two ways
//The first is to configure assetmodule filename in output
module.exports = {
    // ...
  output: {
    // ...
    assetModuleFilename: 'images/[hash][ext][query]'
  }
}
//The second is to configure the filename in the specified resource generator
module.exports = {
  module: {
    rules: [
      {
       test: /\.html/,
          type: 'asset/resource',
        generator: {
          filename: 'static/[hash][ext][query]'
        }
        }
    ]
  }
}

Rule.generator.filenameAndoutput.assetModuleFilenameSame and only forassetandasset/resourceModule type

2. Modify the configuration

module.exports = {
  module: {
    rules: [
             {
               test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
          type: 'asset',
          parser: {
            dataUrlCondition: {
              Maxsize: 10 * 1024 // 10KB if the specified size is less than this value, the inline mode is used
            }
          }
        },
        {
          test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
          type: 'asset',
          parser: {
            dataUrlCondition: {
              Maxsize: 10 * 1024 // 10KB specify size
            }
          }
        },
        {
          test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
          type: 'asset',
          parser: {
            dataUrlCondition: {
              Maxsize: 10 * 1024 // 10KB specify size
            }
          }
        }
    ]
  }
}
  • design sketch

    Pictures can be displayed normally, and audio fonts are the same, so they will not be displayed one by one

[basics] webpack5 build vue3 + typescript basic development environment

Vue3 related configuration

Core dependency / plug-in / loader

npm install -S [email protected] [email protected] [email protected] [email protected] @vue/compiler-sfc
  • Vue / Vue router / vuex correspond to version 3. *
  • The import method of vueloaderplugin has changed
  • vue- [email protected] Currently, you need to specify your own version (the configuration is as follows)
  • Added @ Vue / compiler SFC to replace the original Vue template compiler
  • Related webpack configuration
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
  ...
  module: {
    ...
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'vue-loader'
          }
        ]
      }
    ]
  },
  plugins: [
    ...
    new VueLoaderPlugin()
  ]
  ...
}

So far, the basic support of vue3 can be realized

Extended configuration

Typescript

Vue3 better supports ts, so here we add TS support to the project

There are two options:

1. npm i typescript ts-loader -D
 2. In babel7 version, @ Babel / preset typescript ` preset is added
  • On the difference between the two methods

    Refer to Zhihu article [why is it better to compile typescript with Babel]( https://zhuanlan.zhihu.com/p/376867546 ), make your own choice

The TSC configuration has been used before. Try babel7 here. The configuration is as follows

//Official related links 
// https://babeljs.io/docs/en/babel-preset-env#usebuiltins
// https://babeljs.io/docs/en/babel-preset-typescript
//Correlation dependency
"babel-loader": "^8.2.2",
"@babel/core": "^7.14.8",
"core-js": "^3.17.2",
"regenerator-runtime": "^0.13.9",
"@babel/preset-env": "^7.14.8",
"@babel/preset-typescript": "^7.15.0",
"@babel/plugin-proposal-class-properties": "^7.14.5",


//Babel.config.js configuration
module.exports = function (api) {
  api.cache(true)

  const presets = [
    [
      '@babel/preset-env',
      {
        targets: 'last 1 version,> 1%,not dead',
        corejs: 3,
        Usebuiltins: 'usage' // load on demand, reduce the packaging volume, and automatically introduce core JS and regenerator runtime
      }
    ],
    [
      '@ Babel / preset typescript', // reference typescript plug-in
      {
        Allextensions: true // all file extensions are supported, otherwise using ts in Vue file will report an error
      }
    ]
  ]
  const plugins = [
    '@babel/proposal-class-properties'
  ]

  return {
    presets,
    plugins
  }
}

Add the shims-vue.d.ts file under the SRC folder to solve the Vue type error

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

Eslint

In team development, reasonable code specifications are conducive to code maintenance and mutual cooperation, but each team pair will have its own agreed specifications, so there is no unique standard here. Here, select initialization recommendation rules

  • Initialize the configuration file [the operation interface is shown in the figure below]
npm install eslint eslint-webpack-plugin -D
//Initialize the configuration file [the operation interface is shown in the figure below]
> eslint --init                      
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · vue
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser✔ What format do you want your config file to be in? · JavaScript
The config that you've selected requires the following dependencies:

[email protected] @typescript-eslint/[email protected] @typescript-eslint/[email protected]
✔ Would you like to install them now with npm? · No / Yes
Installing [email protected], @typescript-eslint/[email protected], @typescript-eslint/[email protected]

[basics] webpack5 build vue3 + typescript basic development environment

  • Custom rules can be configured in the. Eslintrc configuration file
//Custom rules can be configured in the. Eslintrc configuration file
"rules": {
  // override default options
  "comma-dangle": ["error", "always"],
  "indent": ["error", 2],
  "no-cond-assign": ["error", "always"],

  // disable now, but enable in the future
  "one-var": "off", // ["error", "never"]

  // disable
  "init-declarations": "off",
  "no-console": "off",
  "no-inline-comments": "off",
}
  • Introducing shared configuration

    Note that the third-party sharing configuration customization needs to be modified according to the third-party rules

//Or introduce the shared configuration standard / airbnb / prettier in extensions. You need to install the corresponding dependencies
//For example: NPM install -- save dev eslint config standard eslint plugin promise eslint plugin import eslint plugin node
//When the same rule is used, the back overrides the front
"extends": [
  "eslint:recommended",
  "standard"
  "plugin:vue/essential",
  "plugin:@typescript-eslint/recommended"
]
  • Eslint auto repair
//Eslint automatically repairs and adds a webpack script. See the official document for specific parameters
"scripts": {
  "lint": "eslint --fix --ext .ts,.js,.vue src"
}

Multi environment

Our project is generally divided into production and testing environments, and the corresponding webpack configuration must be different,

First, the webpack configures the mode itself to provide three modes (empty mode) development (test mode) production (production mode). The specific purposes can be viewed:Specify mode

Then we can distinguish three files according to different modes

Basic general configuration: webpack.base.config.js

Test mode configuration: webpack.base.config.js

Production mode configuration: webpack.base.config.js

  • The specific configuration will not be written. You can think about how to engineer these configurations, which are basic configurations and which are unique to the corresponding mode. Configure the corresponding mode according to the official document description of each plugin loader
  • Configure corresponding script

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

Problems encountered

  • The following error messages occur when using the < router view / > component,

    [Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js"

    The component provides template options, but the Vue build does not support runtime compilation and configure your bundle aliasvue: vue/dist/vue.esm-bundler.js

    In fact, Vue cli scaffold has some settings. I wonder if you noticed it when you used it

    Specific referenceOfficial documents

    Configure Vue alias

    resolve: {
      alias: {
          'vue': 'vue/dist/vue.esm-bundler.js'
      }
    }

Write at the end

Here we are《webpack5+vue3+typescript》The purpose of this article is only to provide a basic idea for building a basic vue3 development environment. The actual development details are not limited to this, such asWebpack details configurationAnd later developmentConstruction speed optimizationProblems, especially with regard to construction optimization, there are still large changes in weback5 compared with weback4, especially when the project is getting larger and larger. Later, I have the opportunity to write another article on weback5 optimization to study and discuss with his family. The writing style is limited. If there are mistakes in the article, I hope you can point out and correct them!

Finally, tips: when learning new knowledge, you can refer to well written blog posts, and you must be careful where you don’t understand

Look at the document!

Look at the document!

Look at the document!

webpack

vue3

babel

[basics] webpack5 build vue3 + typescript basic development environment