(Thousand words) webpack with Vue project

Blog post introduction: Refused to be a CV front-end

1. We usually use vue-cli scaffolding to quickly build projects (vue-cli is based on webpack), but we don't know the principles and details, which makes us unable to configure and solve some detailed problems by ourselves.

2. In order for us to better understand the vue-cli implementation process, we need to learn to use webpack to create a complete project from scratch from an index.html file (including babel, style preprocessor, vue, webpack plugin, dev -server, proxy, etc.

Table of contents: 

1. What is webpack?

1.1 Install webpack: (requires node environment) Node.js

1.2 Use the terminal command webpack 

1.3 Import and use packaged files

2. Understand the configuration files of node and webpack! 

2.1 package.json (belongs to node)

2.2 package-lock.json (node)

2.3 webpack.config.js (webpack) !

3. Entry and exit (entry, output)

3.1 Entry

3.2 Export (output)

4. loader 

4.1 First understand the webpack packaging rules

4.2  css-loader、style-loader、less-loader

4.3  file-loader、url-loader (webpack 4)

~1. file-loader

~2. url-loader

4.4 asset-module (resource module), webpack 5

5. Babel-loader (Babel)

1. What is Babel?

2. Learn to install and configure presets:

3. Configure rules:

Stage summary:

6. Plugin

6.1. What is a plugin:

6.2. Basic usage and clean-webpack-plugin

6.3. html-webpack-plugin

7. Local service (DevServer)

7.1. Installation and use:

7.1.1. Installation:

7.2.2. Configuration:

7.3.3. Enter the service port

7.3.4. Configure port number (port) and host name (hostname) by yourself

7.2. Hot Module Replacement (HMR)

8. Configuration file separation

9. proxy agent

10. Resolve

11. Use the vue library, and .vue single-file components

11.1 Using the vue library:

11.2. vue single file component


1. What is webpack?

Let's listen to an official statement first:

1. webpack is an open source front-end packaging tool. webpack provides a modular development method that front-end development lacks, treats various static resources as modules, and generates optimized code from it.
2. Node.js must be installed before using Webpack. One of the features of Webpack is the use of loaders to convert resources into modules. Developers can customize the order and format of loaders to meet the needs of the project.

A small example to get acquainted with webpack 

cd3ec385d08d49d39701e4622427098e.png

1. We import index.js in index.html 

2. Then import sayHello.js from the js folder in index.js 

482da4f40c714e8b91e33e0b017ccdb6.png

c253ffef0333441dadbbd84254b5aa6e.png

In order to support this modular writing method, webpack is required to package this file


1.1 Install webpack: (requires node environment) Node.js

Terminal command: npm i webpack -g (install webpack globally)

Note that we need to install another webpack-cli , npm install webpack-cli -g

Execute webpack -v to check whether the installation is successful

1.2 Use the terminal command webpack 

First open the terminal, and directly use the command  'webpack' to package.

3. The packaged file will generate a dist folder, put it in the root directory of the project, and there is a packaged main.js file in it. main.js is as follows:

c557841410294ddb8af2032caef87c31.png

2d32addd50e742ef8ebc03dae59713a1.png

1.3 Import and use packaged files

Introduce dist/main.js  in the index.html file


2. Understand the configuration files of node and webpack! 

2.1 package.json (belongs to node)

~1. What is package.json? This is a configuration file that contains the project name, packaging entry (main), and the version of the required dependency package. We can create a new one in the root directory, or enter npm init in the terminal ( or npm init -y This is a simple way of writing, you can directly generate the following configuration file)

66c1c684822b42598b4385192219e8b0.png

We can see what we are familiar with, 'main' : 'index.js', this is the default packaging entry, which is why we must create a new index.js file in the src directory at the beginning , and the name cannot be changed.

~2. If you use npm init, you will be able to enter custom "name", "version", etc. in the console

We recommend the command npm init -y

As shown in the figure, the npm init console is used to display. At this time, you can get the same package.json file by entering yes. It is to let you enter some configurations. We don’t actually need it. You only need to enter the Enter key, and enter yes in the last step. up.

45e193c9b2ce4e868ee8cd1461650bd5.png

~3. Use this file:

Modify the script (script) configuration item to "runpack": "webpack" , you can enter npm run runpack in the terminal , and let our npm boss help us run webpack.

Note: It contains all our dependent packages and corresponding versions. Executing npm install will download them according to the version information in this file. The downloaded dependent packages will be placed in the node_modules folder in the root directory.

2.2 package-lock.json (node)

lock: Chinese means lock , which is to lock the version of the dependent package to prevent errors and misunderstandings caused by different programmers using different versions , so we need to lock them up. The popular point is to fix the version of our dependent package to prevent Later errors caused by different versions.        

3928422cbf594b08a56f50a02d524557.png

2.3 webpack.config.js (webpack) !

webpack.config.js (or webpack.config.json ) file, all configurations of webpack are written in it.

Concept | webpack Chinese documentation

First understand the writing rules of the webpack.config.js file. The entire file is exported using module.exports = {write key-value pairs inside }, as follows:

51fd071ff73f4070a20ee1104028f098.png


3. Entry and exit (entry, output)

3.1 Entry

The entry configuration item is used to specify the configuration of the webpack packaged entry js file, and a path can be specified. The default configuration of this item is ' ./src/index.js ' , which is why we created a new file index.js at the beginning and cannot rename it.

3.2 Export (output)

This item specifies an object, and the first attribute path also specifies a path. The default is to specify the dist folder under the root directory , only

If we want to specify that we need to import a path ( path ) module, as follows:

filename specifies a file name, which is the packaged file name of index.js, and the effect can be seen by importing this file.

const path = require('path');

2221557f9e2546af9720d27aeaca908e.png

Note : At this point our index.html is still in the original folder, we first use this original file to import bundle.js to see the effect, and then go back to solve this problem after learning the plugin plug-in later.


4. loader 

4.1 First understand the webpack packaging rules

Files (modules) that are not dependent will not be packaged . For example, if you create a new element.js under the js folder, this file will not be packaged by webpack, because it is not dependent, so it is not necessary. It will be packaged. Of course, some other static resources (such as pictures and videos) will have their own packaging and deployment methods, which will be mentioned later.

Note: We need to repackage every time the dependent files are modified. In the future, we will use plug-ins ( plugin ) to solve this problem. Let’s sell it first.

As a middleman , webpack packs a bunch of files into resources that browsers can recognize. We can see the power and importance of webpack.

48e70715835745e1977fe07ac45d21e8.png

Walkthrough :

We create a new element.js under the js folder to create an element on the page. Be sure to import element.js in index.js.

edc6d4b48b7d4b9692109c78b0ca9cb8.png

import './js/element.js'

f7e9b9cbce1d487688379c62fbb73989.png

Set the style:

Write a little css code in the css/element.css file , as follows:

41f17cd798c8428288f7cb351ca67e79.png

Then go to index.js or element.js to import it , but it will report an error

15876eab2dfb4676a3fcb072a425acb1.png

A thing called a loader is mentioned here , so what is a loader?


4.2  css-loader、style-loader、less-loader

Let's first understand what a loader is. A loader is like a converter (loader) , which can convert different module files into corresponding files, such as converting typescript to javascript, converting built-in pictures to data_url, etc. Here we use it . Let's import the css file directly in the js file . Maybe my friends have doubts. I used to use css in < style > or < link > to import external css files. That's right. In fact, webpack is also like this. The basic principle It will not change, the loader is to allow you to easily import module codes to improve efficiency , and leave the rest to our powerful loader .

The first step: install css-loader , use npm install css-loader -D , only partial installation is required here.

Note: Here we just downloaded a dependency package, we haven’t told webpack how to use it, that is, we need to configure a module (module) rules (rules) in the webpack.config.js file, (why is it a module, because webpack It also parses css as a module , and we will talk about the configuration of the module later, here is a brief introduction, we mainly configure rules).

Step 2: In the rules configuration, select ( test ) the file type and use ( use ) the specified loader. The configuration is as follows:

module: {
    rules: [
        { test: /\.css/, use: "css-loader" } /正则表达式/ ,\.跟一个文件扩展名
    ],
  },

Step 3: Pay attention, we didn’t say that webpack also uses the most classic and original way to make css take effect . It is useless to have a parsed css code. To make it take effect, we need a The new thing (style-loader), let it generate a style tag , so that the browser can recognize it.

Step 4: Install style-loader: npm install style-loader -D

Step 5: Configure rules

Although our js code is executed from top to bottom and left to right
, it is executed from bottom to top and right to left in the module file

code show as below:

module: {
    rules: [
        { test: /\.css/, use: "style-loader" }, 
// 这是第二个执行的,虽然我们的 js 代码是从上往下执行
// 可是在模块文件里是 从下往上执行的
        { test: /\.css/, use: "css-loader" }, 
// 这是第一个执行的
    ],
  },

Step 6: If we ​​such as less and sass, then we still need to use the corresponding loader . I believe everyone already knows how to use it. First download the dependency package: npm install less-loader -D

Reconfigure. We use a simple notation.

​​​​​​

4.3  file-loader、url-loader (webpack 4)

~1. file-loader

When we build a project, we need some resources , such as some pictures, videos, etc., we can use file-loader to send files to the output directory (dist folder) .

We prepare a picture and put it in the asset folder under the src directory . (We go to the element.css file to use this picture in the form of background, otherwise it will not be parsed)

~~1. Install file-loader: npm install file-loader -D

~~2. Add a new rule in the module configuration:

{
        test: /\.(jpe?g|png|gif)$/i, // 匹配一些图片格式,i 表示忽略大小写
        use: [
          {
            loader: 'file-loader',
            options: {
              esModule: false // 不使用模块解析的语法,防止图片不显示
              // 一些自定义选项
            }
          }
        ],
        type: 'javascript/auto' 
        // file-loader 是 webpack4 的,我们使用的是 webpack5,配置防止资源重复

      }

~~3. Configuration file name and output path:

{
        test: /\.(jpe?g|png|gif)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              esModule: false, // 解决版本问题
              outputPath: 'imgs', // 会在根目录新建一个 img 文件夹
              name: '[hash:6]-[name].[ext]', 
              // hash 是 哈希值,:后跟一个数字控制位数
              // name 是原文件名,ext 是扩展名
            }
          }
        ],
        type: 'javascript/auto' // 解决版本问题
      }

The effect is as follows: 

 

~2. url-loader

url-loader has the ability of file-loader to parse files . It can convert the file into base-64 encoding and put it in the js file. This can reduce the burden on the server and set a dividing line ( limit: limit ).  

The configuration is as follows:

If it is converted, there will be no imgs folder, only one bundle.js, which will have the corresponding code.  


4.4 asset-module (resource module), webpack 5

We used the file-loader and url-loader of webpack 4 at the beginning , and there is a new resource module type in webpack 5 , which can complete resource packaging without using loader

The first configuration method : add a new assetModuleFilename in the output configuration item

output: {
    // 出口
    path: path.resolve(__dirname, "dist"), // 使用 path 模块,在根目录新建文件夹
    filename: "bundle.js", // 指定打包的 js 文件名
    assetModuleFilename: 'asset/[hash:6]-[name]-[ext]' // 指定文件夹名,和资源各自文件名
  },

The second configuration method :

{
        test: /\.(jpe?g|png|gif)$/i,
        type: 'asset/resource', // resource 表示为图片等资源
        generator: {
          filename: 'asset/[hash:6]-[name]-[ext]' // asset 指定文件名,后者指定文件名
        }
      }

The effect is as follows:


5. Babel-loader (Babel)

1. What is Babel?

Babel is an independent tool that converts the advanced syntax of es6 and above to es5 to be compatible with browsers that do not support es6 and above. It is a very powerful javascript compiler.

We can find that the bundle.js file we have packaged now has es6 syntax:

2. Learn to install and configure presets:

        *. Install: npm install @babel/core @babel/cli -D

      *. This is the core code and Babel scaffolding   with Babel installed

        *. Install the Babel preset: npm install babel-preset-env -D

        *. Create a new babel.config.js configuration file , because we have installed a preset, so we can export a preset in the file: as shown in the figure:

        

3. Configure rules:

        *. Then you still need a corresponding loader, install:

        *. npm install babel-loader -D

  

Write an arrow function in index.js, and after packaging, it is found that bundle.js has become a common syntax         

  

​​​​​​After packaging, you can see the following common functions:

Stage summary:

1. We understand what is webpack and its packaging process;

2. We understand the functions of package.json, webpack.config.js  , node_modules and other related configuration files, and slowly start our own personalized configuration;

3. We took css-loader, file-loader, and babel-loader as examples to understand the role of loader and download configuration. Loader and plugin (plug-in) are the reasons why webpack is powerful . We need to learn a lot of plugins and loaders, so we can We can configure the configuration we want by ourselves, instead of only using vue-cli , but not knowing some of its simple principles, which is why we learn webpack.

4. We have to gradually realize that the front end is html, css, js, and all other things are to improve the efficiency of programmers typing code. Everything our webpack does is to return to the original starting point...


6. Plugin

6.1. What is a plugin:

Plug-ins are webpack's pillar functions . Plug-ins appear to make up for the lack of loaders (such as adding browser prefixes to css codes) . Webpack itself also provides many plug-ins. The essence of a plug-in is also a javascript object with an apply method .

6.2. Basic usage and clean-webpack-plugin

6.2.1. Installation: npm install clean-webpack-plugin -D

6.2.2. Import this dependency in webpack.config.js and instantiate it in the plugins property.

6.2.3. The configuration is as follows: In the future, there is no need to delete the dist folder every time.

6.3. html-webpack-plugin

Didn't we say at the beginning that there is no index.html file in the dist folder ? We can easily solve this problem with the help of html-webpack.plugin

6.3.1. Installation: npm install html-webpack-plugin -D

6.3.2. Import and configuration:

const  HtmlWebpackPlugin  = require('html-webpack-plugin')
...
plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin()
  ]

The visible effect is as follows: a simple html file is obtained 

6.3.3. Extension: Use Vue's html template packaging

Although we got an html file, but this file is too simple , many things are missing, such as icons are not imported. If we want to specify a rich html file as a template and let the html-webpack-plugin plug- in generate index.html according to this template (template) , we need to configure it.

~1. We use the index.html file in the project built by vue-cli as our template:

The content of vue's index.html is as follows, copy and replace our index.html

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

After replacing the file, let's configure it as follows, passing in a template attribute (specify a file path):

Then you can get an error:

This is the problem with BASE_URL, specifically in this code:

<link rel="icon" href="<%= BASE_URL %>favicon.ico">

For normal vue projects, BASE_URL is ' ./ ' ,

As shown in the picture above, the icon icon can be displayed normally (the icon icon is the icon on the left side of the web page title)

6.3.4. DefinePlugin、copy-webpack-plugin

1. DefinePlugin is a plug-in that comes with webpack, no additional download is required , it is very easy to use, and can replace variables in the code with other values ​​​​or expressions.

2. copy-webpack-plugin is a plugin for copying resource files, here is used to copy ico icon resources, download: npm insall copy-webpack-plugin -D

~1. Put our icon in the public directory under the root directory. We need to configure BASE_URL to be the path we want, depending on where we copied the icon icon. We assume that it is placed under the dist folder asset folder

~2. Configure as follows:

const  DefinePlugin = require('webpack').DefinePlugin
const  CopyPlugin = require('copy-webpack-plugin')
...
 new CopyPlugin({
      patterns: [
        {
          from: 'public', //复制入口
          to: './asset' // 复制出口
        }
      ]
    }),
    new DefinePlugin({
      BASE_URL: "'./asset/favicon.ico'" // 替换为我们的出口地址
    })

In this way we can get the following effect:

The browser effect is as follows:

 


7. Local service (DevServer)

We used packaging before, and we have to repackage every time we modify the code . Although we can repackage and update the page through the vscode plug-in, it is not convenient enough. What we want is to modify a line of code and press the save button The page will be automatically refreshed, and we need to mention a new thing - DevServer , which can provide a local service .

7.1. Installation and use:

7.1.1. Installation:

npm install webpack-dev-server -D

7.2.2. Configuration:

This time we first configure a script in package.js of npm:

"scripts": {
    "runpack": "webpack",
    "serve": "webpack server", // webpack server 才是真的开启服务的命令
    "jiaoben" : "webpack server" // 我们可配置一些其他的脚本,使用 npm run '配置的脚本'
  },

We are used to let node start the service, of course you can also execute directly: webpack server

Just like before, you can directly execute the webpack command to package, and then configure an npm run runpack.

7.3.3. Enter the service port

7.3.4. Configure port number (port) and host name (hostname) by yourself

To configure the hostname and others by ourselves, we need to configure the DevServer in webpack.config.js as follows:

7.2. Hot Module Replacement (HMR)

Hot module replacement means that changing the code page of a module part will only change the corresponding part . We enable the hot module replacement service through hot: true , and the configuration is as follows:

7.2.1. Add in the index.js file, the following is self replacement (self)

const foo = (regs) => {
    console.log("我是 es6 语法");
    console.log("替换一次吧")

}
foo()

module.hot.accept( //开启自身模块替换
    console.log(`模块替换了`),
)

We change some prints in the foo function, and we can find that the console is as follows. The old prints have not been deleted, indicating that the hot module has been replaced successfully .

 

 7.2.2. Module update is to import other module updates, here you can import ' ./js/element.js ', and modify the code in element.js in the future will also update the module.

if(module.hot) { // 模块更新
    module.hot.accept('./js/element.js')(
    console.log(`模块替换了`),
)
}

8. Configuration file separation

We mentioned the development mode (mode) before . In the production environment ( production ), we don’t need to pack and clear the old folders, so we don’t need the clean-webpack-plugin plugin. Some configurations are development ( development ) and production Both are required, then we call it the public configuration ( webpack.common.js ), so we need to put the development mode configuration file ( webpack.dev.js ) and the production mode configuration file ( webpack.prod.js ) and public configuration ( webpack.common.js ) splicing ( merge ), this process depends on a plugin ( webpack-merge-plugin ).

We prepare the corresponding three files in the root directory. 

Then go to install the plug-in for splicing:

npm install webpack-merge-plugin -D 

Under webpack.prod.js:

Under webpack.dev.js:

So how to specify the configuration, we configure the node scripts script in package.js , and use --config to specify the corresponding configuration file:

9. proxy agent

Proxy ( proxy ) is used to solve the problem of cross-domain browsers . Cross-domain is a kind of security strategy. It can only be accessed when the security protocol, host name and port are consistent. In many cases, it is difficult to achieve. We need to carry out Proxy, configured through the proxy configuration item of webpack:

We first use axios to initiate a request, first download and install axios: npm install axios , and then write the following code in index.js:

import axios from "axios"
...
axios.get("http://localhost:9999").then((res)=>{console.log(res);})

We changed the port to 9999 at the beginning, but it is definitely not accessible now, and the error is as follows:

But if we modify "http://localhost:8888" to "/api" and proxy "/api" to "http://loacalhost:9999" through proxy , we can get our local server and control it station printing.

as follows:

Then let axios access '/api' directly in index.js 

But the ending is still unsatisfactory. Let's look at the error message and find that the address we visited is "http://localhost:9999 /api  ",

This is not accessible, there is no such path at all, we need to rewrite the path ( pathRewrite ):

 proxy: {
      "/api": {
        target: "http://loacalhost:9999",
        pathRewrite: { "^/api": "" }, //重写 /api 为空
      },
    },

Let's see the effect next:

 You can see that we have accessed the data of the local server.


10. Resolve

We sometimes find that the path is very cumbersome to write, such as this: import element from ' . /  js  / element  . js ' or import " . / styles / element  . less  ",

If we don't want to write the path and suffix name, then we can simplify our work through resolve analysis.

Add configuration as follows:

resolve:{
    modules: ["node_modules"], // 配置依赖包的默认路径,
    alias: { 
      "js": path.resolve(__dirname,"./src/js"), //配置样式简单的路径
      "@": path.resolve(__dirname,"./src") // 把 src 这个常用目录修改为 @
    },
    extensions: [".js",".less",".css",".vue"] //配置了这些我们就不写那些后缀名啦
  },

11. Use the vue library, and .vue single-file components

Vue is a very useful javascript library. Vue 3 has been released now. We can directly import and use the library file, or use the single file (SFC) form. It will be easier to use the library file directly. Let's try it first. .

11.1 Using the vue library:

~11.1.1. Install vue3

npm install vue@next 

~11.1.2. Import createApp method to create an instance

import { createApp } from "vue/dist/vue.esm-bundler.js" // 导入创建实例方法

const App = createApp({
    template: `<h2>我是通过vue生成的{
   
   { title }}</h2>`, // DOM 模版 {
   
   { 模版字符串 }}
    data(){
// vue2 写法
        return {
            title: "标题" // 数据
        }
    }

})

App.mount("#app") //挂载到一个 id 为 app 的 DOM 元素上

The effect is as follows:

11.2. vue single file component

What is Single File ( SFC )?

In order to better adapt to complex projects, Vue supports .vue to define a complete component in a file with the extension , instead of using  Vue.component the registered component. Then we can use webpack to package this component.

11.2.1 We first create the following file (App.vue) in the src directory.

11.2.2. Import this file in index.js


import { createApp } from 'vue/dist/vue.esm-bundler'
import App from "@/vue/App" //导入
...
createApp(App).mount("#app") // 创建实例并挂载(mount)

Next, an error must be reported. Our .vue single file must be parsed by the loader .

Install the loader:

npm install vue-loader -D

this alone is not enough

We also need to install a vue single file parser:

npm install @vue/compiler-sfc -D

Then remember to go to webpack > module > rules to configure:

{
        test: /\.vue$/,
        use: {
          loader: 'vue-loader'
        }
      }

However, an error will still be reported. We checked the information and found that it mentioned a plugin: VueLoaderPlugin 

This plugin comes with vue, just import and configure it directly:

import { VueLoaderPlugin } from "vue-loader/dist/index";
...
plugins: {
    new VueLoaderPlugin()
}

Now you can see the effect


Summarize:

We have mastered the preprocessing of the project using  the webpack  packaging tool, and can use the Vue framework to help us build a simple project.

Vue also has a lot of built-in libraries, such as vuex, vue-route , we will not study these here, the focus is to grasp the ins and outs of the project built using vue-cli, and you can make some simple modifications yourself, maybe This article cannot significantly improve your ability to develop projects, but at least you are not just a player who can only use vue-cli scaffolding.

Thank you for browsing here, there are many shortcomings in this article, point out a lot and make progress together!

Guess you like

Origin blog.csdn.net/m0_66492535/article/details/127761060