[ten thousand words step by step] package vue project with webpack (basic production environment)

Posted by jake8 on Mon, 24 Jan 2022 13:23:05 +0100

This project is a hands-on project. It uses the new novice guide page created by Vue cli. The project itself does not have particularly complex logic, and Vue learning is not involved here. It will only be completed through gradual decomposition, and the final packaging of the project will be completed by using webpack.

The plugins and loaders used this time are:

  • webpack & webpack-cli

  • vue-loader & vue-template-compiler

  • style-loader & less & less-loader

    This can be modified according to specific project requirements. LESS is used here, so it needs to be additionally equipped with LESS & LESS loader

    css only users can only use style loader

  • file-loader & url-loader

    There is also an alternative relationship here. URL loader plays the role of optimization. Its fallback is file loader, so file loader must be installed when using URL loader

    On the contrary, only file loader can be used without installing URL loader

  • htmlWebpackPlugin

    It solves the migration and template problems of HTML files, that is, entry files

  • clean-webpack-plugin

    Automatically clear previously compiled files

  • copy-webpack-plugin

    It meets the needs of migrating other static files

Project analysis

The structure is as follows. The files to be compiled include vue, less and JavaScript, and the files to be compressed include packaged JavaScript and HTML files.

Note *: this project is an initial project created using Vue cli, but the automatic packaging part of the scaffold is removed.

Realize basic functions

This part mainly implements some basic functions. This project is already an initialized node project. Otherwise, you need to use the init command for initialization.

Install webpack and webpack cli

D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base>npm i webpack webpack-cli -D

i is the abbreviation of install and - D is the abbreviation of -- save dev, so you can install webpack and webpack cli as development dependencies.

View package JSON file, you will find that devdependencies has been updated:

{
  "devDependencies": {
    "webpack": "^5.41.0",
    "webpack-cli": "^4.7.2"
  }
}

At this time, a new script command can be added to let npm run webpack:

{
  "script": {
    "build": "webpack"
  }
}

At this time, trying to run npm run build on the command line will get a lot of error results, but this can prove that the command can be run normally.

D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base>npm run build

> vue-app-base@0.1.0 build D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base
> webpack

assets by status 0 bytes [cached] 1 asset

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

ERROR in main
Module not found: Error: Can't resolve './src' in 'D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base
# Save a lot of error information
webpack 5.41.0 compiled with 1 error and 1 warning in 163 ms

Add profile

Finally, create a new webpack. Net in the root directory config. JS is used as the entry of webpack, and is nested into the template to configure the packaging mode, entry and exit files.

The configuration file of webpack can export an object, and the corresponding configuration options can be completed by exporting the properties of the object.

// npm original module
const path = require('path');

module.exports = {
  // Entry file
  entry: './src/main.js',
  // Exported part
  output: {
    // Exported file name
    filename: 'bundle.js',
    // The path where the exported file name will be placed
    path: path.resolve(__dirname, 'dist/'),
  },
};

Run npm run build again at this time, and the following results will be obtained:

D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base>npm run build

> vue-app-base@0.1.0 build D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base
> webpack

assets by status 4.16 KiB [cached] 1 asset
runtime modules 718 bytes 3 modules
cacheable modules 770 bytes
  ./src/main.js 169 bytes [built] [code generated]
  ./src/App.vue 537 bytes [built] [code generated] [1 error]
  ./src/style.less 64 bytes [built] [code generated] [1 error]
# Omit a pile of error messages
webpack 5.41.0 compiled with 4 errors and 1 warning in 216 ms

This time, four errors and one warning are called out, which is a good thing. At least list all error messages one by one, so that you can start debug ging. What I fear most is not that there are many wrong information, but that there is no clue about the wrong information and I don't know where to start.

webpack gives several problems in the project, namely:

  • WARNING in configuration

    This means that the mode is not set and will be developed in the production environment by default

  • ERROR in ./src/App.vue 1:0

    This hint is obvious. webpack says:

    You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.

    A Vue loader is needed to solve the problem

  • ERROR in ./src/main.js 1:0-21

    This problem should also be the same. The specific error information is as follows:

    Module not found: Error: Can't resolve 'vue' in 'D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base\src'
    
  • ERROR in ./src/style.less 1:0

    The problem is the same as the lack of loader:

    You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.

  • ERROR in bundle.js from Terser

    This problem belongs to the problem of output file. First solve the problem of packaging above, and then see if this problem will occur

mode problem

This problem is easy to solve. At this stage, the command line parameters in scripts will be modified to set to the development mode:

{
  "scripts": {
    "build": "webpack --mode=development"
  }
}

Similarly, when you run npm run build again, you will find that there is one missing error message:

webpack 5.41.0 compiled with 3 errors in 103 ms

The last error in bundle JS from terser disappeared. That is to say, the remaining three errors are all errors reported during development, so you can start to prepare for the implementation of the open loader and plugin.

In addition, although an error is reported at this time, the dist directory can be displayed to prove that webpack has been run at least once and the packaging file has been exported - this time, it can be confirmed that there are no problems with the installation and basic configuration of webpack:

vue loader and related

vue loader It is a webpack plug-in, and the configuration here is also implemented with the official documents.

  1. Install Vue loader and Vue template compiler

    npm install -D vue-loader vue-template-compiler
    # I suddenly realized that the error of cannot find Vue was because I didn't download the package Vue listed in JSON
    # So download again and download the required dependent packages
    npm install
    
  2. Rewrite webpack.com according to the contents of the official documents config. JS content

    // New content
    const { VueLoaderPlugin } = require('vue-loader');
    
    module.exports = {
      // New content
      module: {
        rules: [{ test: /\.vue$/, loader: 'vue-loader' }],
      },
      plugins: [new VueLoaderPlugin()],
    };
    
  3. Continue to follow the official documentation, download and install the required dependencies, and rewrite the webpack config. js

    # babel is responsible for parsing JavaScript
    npm install -D babel-loader @babel/core
    # The other two are responsible for parsing CSS
    npm install -D vue-style-loader css-loader
    # This is also a required plug-in, otherwise an error will be reported
    # It is not listed in the official documents. If there are different error reports, you must read the error information
    npm i -D @vue/cli-plugin-babel
    
    // New content
    const { VueLoaderPlugin } = require('vue-loader');
    
    module.exports = {
      // The contents in module are new contents
      module: {
        rules: [
          // Parsing Vue files
          { test: /\.vue$/, loader: 'vue-loader' },
          // It will be applied to ordinary js ` file
          // And ` ` < script > ` block in vue ` file
          {
            test: /\.js$/,
            loader: 'babel-loader',
          },
          // It will be applied to ordinary css ` file
          // And ` ` < style > ` block in vue ` file
          {
            test: /\.css$/,
            use: ['vue-style-loader', 'css-loader'],
          },
        ],
      },
      plugins: [
        // Please make sure to introduce this plug-in!
        new VueLoaderPlugin(),
      ],
    };
    
  4. When npm run build is run, there are only two error messages left, one is png package error (lack of image processing) and the other is less package error (lack of less)

Solve CSS loading

The content loaded by CSS is officially provided by webpack: less-loader Therefore, the error reporting information will be solved step by step here

  1. Download required dependent packages

    # This is style loader, which is required for the following configuration
    npm install style-loader --save-dev
    # This is related to less
    npm install less less-loader --save-dev
    
  2. Modify profile

    Note *: the official document here uses loader, but I don't know why using loader will report an error, so it is changed to use. If you report an error with use, try loader. The version change of webpack may make it very difficult to use

    module.exports = {
      module: {
        rules: [
          // Other places remain unchanged
          // Processing less files
          {
            test: /\.less$/i,
            use: [
              // compiles Less to CSS
              'style-loader',
              'css-loader',
              'less-loader',
            ],
          },
        ],
      },
    };
    
  3. Run npm run build to check

    There is only one png problem left this time

Solve the problem of picture loading

  1. Download the corresponding loader. File loader is used here

    D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base>npm i -D file-loader
    
  2. Modify profile

    module.exports = {
      output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'),
        // New content: modify the path and change it to relative path instead of absolute path
        publicPath: './',
      },
      module: {
        rules: [
          // Omit other configurations
          // Processing png pictures
          {
            test: /\.png$/i,
            // If you directly use use use: "file loader" as above
            // The picture resource is "[object Module]"
            // This is because the new file loader automatically opens the ES module
            // Manual closing can display correctly
            use: {
              loader: 'file-loader',
              options: {
                esModule: false,
              },
            },
          },
        ],
      },
    };
    

    Note *: the file loader here has some special properties. In order to correctly display pictures, you must set esModule to false

    This is due to different file loader versions. In the low version environment, the default esModule is closed, so it can be displayed correctly. But the version I'm using now is 6.2. By default, esModule is enabled. When esModule is enabled, the path introduced by the picture is "[object Module]" instead of SRC = ". / 26bd867dd65e26dbc77d1e1151ffd36e0. PNG".

  3. Try packaging

    Finally, there is no error message. It seems that it has been packaged successfully.

    D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base>npm run build
    
    > vue-app-base@0.1.0 build D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base
    > webpack --mode=development
    
    asset bundle.js 566 KiB [emitted] (name: main)
    asset 26bd867dd65e26dbc77d1e151ffd36e0.png 6.69 KiB [emitted] [immutable] [from: src/assets/logo.png] (auxiliary name: main)runtime modules 2.04 KiB 6 modules
    modules by path ./node_modules/core-js/ 147 KiB
    modules by path ./node_modules/core-js/internals/*.js 85.2 KiB 114 modules
    modules by path ./node_modules/core-js/modules/*.js 62 KiB 36 modules
    modules by path ./src/ 16.1 KiB 20 modules
    modules by path ./node_modules/style-loader/dist/runtime/*.js 4.12 KiB 4 modules
    modules by path ./node_modules/vue-style-loader/lib/*.js 6.74 KiB
    ./node_modules/vue-style-loader/lib/addStylesClient.js 6.09 KiB [built] [code generated]
    ./node_modules/vue-style-loader/lib/listToStyles.js 671 bytes [built] [code generated]
    ./node_modules/vue/dist/vue.runtime.esm.js 222 KiB [built] [code generated]
    ./node_modules/vue-loader/lib/runtime/componentNormalizer.js 2.71 KiB [built] [code generated]
    ./node_modules/@babel/runtime/helpers/esm/typeof.js 726 bytes [built] [code generated]
    ./node_modules/css-loader/dist/runtime/api.js 1.75 KiB [built] [code generated]
    webpack 5.41.0 compiled successfully in 3548 ms
    

    You can also see new pictures under the packaged Directory:

Note *: if the picture is small, you can use URL loader, which can reduce the number of http requests.

Then, manually copy, paste and modify the index HTML, take a look at the rendering results:

All contents can be displayed normally, and the processing of static resources can be started.

URL loader, image optimization

  1. Download the corresponding loader. File loader is used here

    D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base>npm install url-loader --save-dev
    
  2. Modify profile

    But speaking, vue's logo is just stuck in the size of 8kb, so what is the conventional rule?

    Note that file loader should be changed to URL loader here, and URL loader and file loader cannot be superimposed. The reason is that the fallback function of URL loader is file loader. If two loaders are used at the same time, URL loader will base64 convert the path of the original image file. This causes the converted image to be invisible - the image path is converted, not the image.

    The specific discussion is in an issue of URL loader: url-loader is encoding path instead of image.

    I stepped on a thunder and learned a knowledge point.

    module.exports = {
      module: {
        rules: [
          {
            test: /\.png$/i,
            use: [
              {
                // It was originally file loader, but it should be changed to URL loader here
                loader: 'url-loader',
                options: {
                  // The upper limit is set in official documents, so it won't be changed here
                  limit: 8192,
                  // Similarly, if it is not set to false, esModule will be opened
                  esModule: false,
                },
              },
            ],
          },
        ],
      },
    };
    

Solve the loading of static files

The dawn of victory is close at hand. The next step is just to solve the problem of static resources. The static resource here refers to the index. In public HTML and favicon ico. First, you need to cv the contents under public to dist, and then you need to deal with the template file in HTML.

The plug-in used here is htmlWebpackPlugin, which is also a hint in Vue's native project:

<title><%= htmlWebpackPlugin.options.title %></title>

For specific configuration, see the instructions on github:
html-webpack-plugin

  1. Download and install plug-ins

    D:\lagou-front-12\part2\fed-e-task-02-02\code\vue-app-base>npm i -D html-webpack-plugin
    
  2. Modify profile

    Here is to modify the configuration according to the official documents.

    Note *: BASE_URL is an environment variable, so you need to use deinfeProperty to set it

    // Two newly imported dependencies
    const webpack = require('webpack');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
      plugins: [
        // Set the basic configuration required for webpack
        new webpack.DefinePlugin({
          BASE_URL: JSON.stringify('./'),
        }),
        // An empty dog morning chill will only generate an index HTML, appropriate files will be introduced, but the portal DOM node app is missing, so other configurations are required
        new HtmlWebpackPlugin({
          template: 'public/index.html',
          favicon: 'public/favicon.ico',
        }),
      ],
    };
    
  3. Run npm run build package

    The results are as follows:

    You can see favicon ICO is also packaged, index The contents of HTML are as follows:

    You can see that the title and logo have been dynamically modified, and the content can be rendered normally:

Automatically clear output directory

Now, the contents in dist will be rewritten every time. Although it will not affect the results, it may cause the previously generated files to be left in the folder, resulting in unnecessary waste. The clean webpack plugin will be used to solve this problem. The address of npmjs is: clean-webpack-plugin

Note *: by default, this version will empty the contents of all output directories.

  1. Download and install plug-ins

    npm install --save-dev clean-webpack-plugin
    
  2. Modify configuration

    This configuration changes quickly. You can directly reference it.

    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    
    module.exports = {
      plugins: [
        // The previous configuration remains unchanged
        new CleanWebpackPlugin(),
      ],
    };
    
  3. Run npm run build package

    I ran it successfully, and then I will modify another problem.

Copy static files

When configuring the HTML webpack plugin, I added a favicon ICO, and then found that the Vue project originally had a favicon ICO, another one is added here, and a duplicate code appears:

When I called the clean webpack plugin above, I removed the original favicon configuration, and there was a problem that the pictures were not migrated. Here, find a plug-in to migrate static resources.

The plug-in used here is a plug-in found on the official website of webpack: copy-webpack-plugin

  1. Download and install plug-ins

    npm install copy-webpack-plugin --save-dev
    
  2. Modify configuration

    All we need to do here is migrate favicon ICO, so only this file is set, but copy webpack plugin can actually migrate a single file or an entire folder

    // Daily reference
    const CopyPlugin = require('copy-webpack-plugin');
    
    module.exports = {
      plugins: [
        // The rest remains unchanged
        // Only favico has migrated here ICO this file
        new CopyPlugin({
          patterns: [{ from: 'public/favicon.ico', to: './' }],
        }),
      ],
    };
    

    This completes the favicon Migration of ICO files

last

Package Modify the build in JSON as follows:

// It was development
"build": "webpack --mode=production",

When you run the package command npm run build, webpack will automatically compress the packaged files according to the production environment:

HTML entry file:

Packaged bundle JS file:

In this way, a basic production environment packaging function is realized.

The next step is to learn how to use webpack dev server to configure the development environment - after all, I use the hot update implemented by the live server plug-in here, but it is not guaranteed that everyone uses one editor / IDE, let alone the same plug-in.

Similarly, tree shaping and code splitting are also issues to be considered, which will be learned and configured in the next article.

Finally, Linting should also be added. Maintaining the unity of code style is very helpful for later maintenance.

Topics: Javascript Front-end Vue Webpack