Webpack new features

  • Persistent cache
  • ModuleIds & chunkIds optimization
  • More intelligent Tree shaking
  • Module Federation
  • .

New features for Vue3

  • smaller
  • faster
  • Enhance TypeScript support
  • Strengthen API design consistency
  • Improve their maintainability
  • Open up more low-level functionality

Start the configuration

Create a project

npm init -y

Install required plug-ins and necessary configurations

  1. Install webppack5
npm i webpack webpack-cli webpack-dev-server -D 
Copy the code
  1. CSS analytical
npm i less less-loader css-loader style-loader -D 
Copy the code
  1. vue-loader
npm i vue-loader@next @vue/compiler-sfc -D 
Copy the code

Add the shims-vue.d.ts file to the SRC folder to resolve vUE type errors

declare module '*.vue' {
    import type { DefineComponent } from 'vue'
    const component: DefineComponent<{}, {}, any>
    export default component
}
Copy the code
  1. The template parsing
npm i html-webpack-plugin -D
Copy the code
  1. Install typescript and parse plug-ins
npm i typescript ts-loader --save-dev
Copy the code
  1. Handle image url-loader
npm i url-loader -D
Copy the code
  1. Handle CSS, less
cnpm i mini-css-extract-plugin css-loader less less-loader postcss postcss-loader -D
Copy the code

The configuration is shown in webpack.base.config.js

  1. To deal with ts
npm i typescript ts-loader --save-dev
Copy the code

Ts-loader performs type check and translation for a single process. Therefore, the efficiency is slow. You can use the multi-process solution: Disable type check for TS-Loader, and the type check is performed by the fork-ts-checker-webpack-plugin. npm i fork-ts-checker-webpack-plugin –save-dev

  1. Other plug-ins

Merge plug-in configuration Webpack-Merge

Remove the dist package clean-webpack-plugin generated by Build

Cross-platform cross – env

Create a configuration file and write the configuration (webpack4 is basically the same as webpack5)

Create the build folder, and then create the public configuration file webpack.base.config.js, development configuration file webpack.dev.config.js, and production configuration file webpack.prod.config.js.

webpack.base.config.js

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {VueLoaderPlugin} = require('vue-loader')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const ProgressBarPlugin = require('progress-bar-webpack-plugin')
const path = require('path')
const Dotenv = require('dotenv-webpack')

function getConfigPath(mode) {
  return path.resolve(process.cwd(), `.env.${mode}`)}module.exports = {
    entry: './src/main.ts'.cache: {
      type: 'filesystem'  // Persistent cache
    },
    output: {
        filename: 'js/[name].[chunkhash:5].js'.path: path.resolve(__dirname, ".. /dist")},module: {
        rules: [{test: /\.(t|j)s$/,
            exclude: /node_modules/,
            use: [
              {
                loader: 'babel-loader',},],}, {test: /\.(t|j)s$/,
              exclude: /node_modules/,
              use: [
                {
                  loader: 'ts-loader'.options: {
                    // Specify a specific TS compilation configuration to distinguish the script's TS configuration
                    configFile: path.resolve(__dirname, '.. /tsconfig.json'),
                    // Add a. Ts or. TSX suffix to the corresponding file
                    appendTsSuffixTo: [/\.vue$/].transpileOnly: true // Turn off type detection, that is, value translation},},],}, {test: /\.css$/,
            use: [
              // 'vue-style-loader',
              // 'style-loader',
              MiniCssExtractPlugin.loader,
              'postcss-loader'.'css-loader'],}, {test: /\.less$/,
            use: [
              // 'vue-style-loader',
              MiniCssExtractPlugin.loader,
              // 'style-loader',
              'css-loader'.'postcss-loader'.'less-loader'],}, {test: /\.(gif|jpg|png|woff|svg|eot|ttf)\?? . * $/,
            use: [
              {
                loader: 'url-loader'.options: {
                  limit: 1024,},}]}]},optimization: {
      splitChunks: {
        chunks: 'async'.minSize: 20000.minChunks: 1.// The minimum number of uses
        maxAsyncRequests: 5.maxInitialRequests: 3.minChunks: 1.cacheGroups: {
          // Extract the public js
          commons: {
            chunks: "all".// initial
            minChunks: 2.maxInitialRequests: 5.minSize: 0.name: "commons"}}}},resolve: {
      extensions: [".ts".".tsx".".js".".json"],},plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html'.filename: 'index.html'.title: 'webpack5+Vue3'
        }),
        new VueLoaderPlugin(),
        new MiniCssExtractPlugin({
          filename: "style/[name].[hash:8].css".chunkFilename: "style/[hash:8].css"
        }),
        new ForkTsCheckerWebpackPlugin(),
    ]
}

Copy the code

webpack.dev.config.js

const { merge } = require('webpack-merge')
const common = require('./webpack.base.config')
// const SpeedMeasurePlugin = require("speed-measure-webpack-plugin")
// const smp = new SpeedMeasurePlugin()
module.exports = merge(common,{
    mode: 'development'.devtool: 'source-map'.devServer: {
        port: 9091.// Local server port number
        // hot: true, // hot overload
        // overlay: true // If the code fails, a "floating layer" pops up on the browser page. Similar to vuE-CLI scaffolding
        disableHostCheck: true}})Copy the code

webpack.prod.config.js

const { merge } = require('webpack-merge')
const common = require('./webpack.base.config')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
module.exports = merge(common,{
    mode: 'production'.plugins: [
        new CleanWebpackPlugin()
    ]
})
Copy the code

The configuration script

package.json

."scripts": {
    "server": "cross-env NODE_ENV=development webpack serve --progress --hot --inline --config build/webpack.dev.config.js"."build": "cross-env NODE_ENV=production webpack --mode=production --config build/webpack.prod.config.js"},...Copy the code

4. Configuration tsconfig. Json

{
    "compilerOptions": {
      "target": "esnext"."module": "esnext"."strict": true."jsx": "preserve"."importHelpers": true."moduleResolution": "node"."experimentalDecorators": true."skipLibCheck": true."esModuleInterop": true."allowSyntheticDefaultImports": true."sourceMap": true."baseUrl": "."."types": [
        "webpack-env"."node"]."paths": {
        "@ / *": [
          "src/*"]},"lib": [
        "esnext"."dom"."dom.iterable"."scripthost"]},"include": [
      "src/**/*.ts"."src/**/*.tsx"."src/**/*.vue"]."exclude": [
      "node_modules"]}Copy the code

The project configured here is ready to run, but a few questions remain: Ts can compile to the specified version of JS, so does Babel still need to be used?

TSC’s target only translates syntax and does not integrate polyfill, so Babel is still required.

For example, convert arrow functions to normal functions and aysnc + await to promise. then, this is syntactic translation.

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

So we still need Babel in the project.

Existing solutions for Webpack translation of Typescript:

plan 1 2 3
Single-process scenario (type checking and translation in the same process) Ts – loader (transplieOnly to false) awesome-typescript-loader
Multiprocess scheme Ts – loader (transplieOnly to true + fork – ts – the checker – webpack – the plugin) Awesome-typescript-loader + comes with Checkplugin babel+fork-ts-checker-webpack-plugin

Considering performance and scalability, Babel + fork-ts-Checker -webpack-plugin is currently recommended.

Before babel7, it was necessary to use both ts-loader and babel-loader. The compilation process of ts > TS compiler > JS > Babel > JS. Compiling JS twice is inefficient. But babel7 comes out with the ability to parse typescript, and with this level of support, we can just use Babel without having to go through another TS compilation process.

In Babel 7, we use the new @babel/preset-typescript preset, which, combined with a few plug-ins, can 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 in its own way. Removing typescript eliminates the need for type checking and annoying type errors, which makes compiling faster.

Add Babel to parse typescript

Install the following dependencies --save-dev # webpack loader babel-loader # Babel core @babel/core # Intelligent conversion to the target runtime environment code @babel/preset-env # recall Support for TS class writing @babel/preset-typescript # polyfill @babel/plugin- transform-Runtime @babel/plugin-proposal-class-propertiesInstall the following dependencies --save
@babel/runtime
@babel/runtime-corejs3
"core-js":" ^ 3.11.0"Copy the code

Delete ts-loader and add babel-loader

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

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

module.exports = {
    presets: [['@babel/preset-env',
        {
          useBuiltIns: 'usage'.// Introduce polyfill on demand
          corejs: 3,}], ['@babel/preset-typescript'.// Reference the Typescript plug-in
        {
          allExtensions: true.All file extensions are supported, otherwise using ts in vue files will cause an error},]].plugins: [['@babel/plugin-transform-runtime',
        {
          corejs: 3],},'@babel/proposal-class-properties'
      // '@babel/proposal-object-rest-spread',],}Copy the code

Consider: Vue-CLI automatically creates scaffolding projects that can read configurations according to.env.production,.env.development, how should this be implemented?

Dotenv-webpack can be used with the cross-env NODE_ENV=development environment specified before executing the script.

Other plugins: Speed-measure-webpack-plugin Package speed analysis Webpack-bundle-Analyzer Package result analysis… Of course, there are many other plug-ins.

Finally, attach the code: address