1.Babel

Babal is not very development-aware, but it is an integral part of front-end development

We want to use ES6+ syntax, we want to use TypeScript, we want to develop React projects, they all need Babel

Babel is a tool chain for converting ECMAScript 2015+ code to backward-compatible versions of JavaScript in older browsers and environments, including syntax conversion, source code conversion, etc

1.1. Use the Babel command

Babel itself can be used as a standalone tool (like PostCSS), not in isolation from build tool configurations such as WebPack

If we want to try using Babel from the command line, we need to install the following libraries:

  • @babel/core: the core code of Babel, must be installed
  • Babel /cli: allows us to use Babel at the command line
npm install @babel/cli @babel/core -D
Copy the code

Use Babel to process our source code:

  • SRC: indicates the directory of the source file
  • –out-dir: Specifies the folder dist to output
npx babel src --out-dir dist
Copy the code

1.2. Use of plug-ins

For example, if we need to convert the arrow function, we can use the arrow function to convert the related plug-in:

npm install @babel/plugin-transform-arrow-functions -D
npx babel src --out-dir dist --plugins=@babel/plugin-transform-arrow-functions
Copy the code

Looking at the result of the conversion, we see that const is not converted to var

This is because plugin-transform-arrow-functions does not provide this functionality and we need plugin-transform-block-scoping to do this

npm install @babel/plugin-transform-block-scoping -D
npx babel src --out-dir dist --plugins=@babel/plugin-transform-block-scoping
,@babel/plugin-transform-arrow-functions
Copy the code

1.3.Babel的预设preset

If preset is inconvenient to set one by one if there is too much to convert, we can use preset.

NPM install @babel/preset-env -d

Run the NPX Babel SRC –out-dir dist –presets=@babel/preset-env command

1.4. Implementation principle of Babel underlying compiler

Babel is essentially a compiler

What the Babel compiler does is convert our source code into another piece of source code that the browser can recognize directly

Babel also has a compiler workflow:

  • Parsing
  • Transformation phase
  • Code Generation

Babel execution phase:

Of course, the simplified version of the compiler tool flow above has its own specific work at each stage

1.5. The Babel – loader

Normally during development we might use it through Webpack configuration loader

NPM install babel-loader@babel /core

Set a rule to use our Babel when loading js files:

1.6. The Babel – preset

Configuring the Loader above may require managing a large number of plug-ins

We can simply provide a preset to the Webpack

Webpack loads the list of plug-ins based on our default and passes it to Babel

For example, there are three common presets:

  • env
  • react
  • TypeScript

Install preset-env: NPM install @babel/preset-env

Configure corresponding to PRESET:

1.7. Configuration files for Babel

We can put the configuration information of Babel in a separate file, and Babel gives us two configuration files to write

  1. The babel.config.json (or.js,.cjs,.mjs) file, which can be directly used in the Monorepos project subpackage, is more recommended
  2. .babelrc.json (or.babelrc,.js,.cjs,.mjs) files, the early use of more configuration methods, but for the configuration of Monorepos project is more cumbersome

2. Pack Webpack Vue

Importing Vue: NPM install vue@next

So what happens if we package Vue with the code above?

The interface has no effect and a warning message appears on the console

2.1.Vue is packaged and resolved for different versions

Vue (. The runtime). Global (. Prod). Js:

  • Through the browser<script src = "">Direct use of
  • This is the version of Vue we imported and downloaded via CDN earlier
  • A global Vue is exposed for use

Vue (. The runtime). The esm – browser. (prod). Js:

  • For import use through the native ES module (through the browser<script type="module">)

Vue (. The runtime). The esm – bundler. Js:

  • For build tools such as Webpack, rollup, and Parcel
  • The default in the build tool is vue.Runtime.esm-bundler.js
  • If we need to parse the template, we need to specify vue.esm-bundler.js manually

Vue. CJS (. Prod). Js:

  • Server side rendering use
  • Used in Node.js by require()

Runtime + compiler vs runtime only

Vue writes DOM elements in three ways

  1. templateTemplate approach (often used before)
  2. Write templates from templates in the.vue file
  3. Use the h function to write the content of the render
  • Both methods require specific code to parse them

    • For template, we have to compile a portion of the source code

    • The template in the vue file in option 2 can be compiled and processed by vue-loader

  • In method 3, the h function can directly return a virtual node, that is, a Vnode node.

Vue is divided into runtime + compiler vs run-time only when it lets us choose versions

  • The runtime + compiler contains compiled code for the Template template, which is more complete, but also larger
  • The run-time contains no compiled code for the template version, which is smaller

2.2.VSCode support for SFC files

In real development we use SFC (Single-file Components)

VSCode support for SFC:

  1. Vetur, a Vue supported plug-in that has been used since the development of Vue2
  2. Volar, the official recommended plugin

2.3. Write SFC files


You make a mistake packing

We need the right loader to help us process the files

We install vue-loader:

npm install vue-loader -D
Copy the code

And configure it in webpack’s template rules:

I also need to add @vue/ Compiler-sFC to parse the template

npm install @vue/compiler-sfc -D
Copy the code

Repackage to support. Vue file writing

Configuration of global identifiers

The console will still have a warning

This is the indication of two features, one is using Vue Options, and the other is whether devTools is supported in Production mode

Although they all have default values, it is highly recommended that we configure them manually

3. Set up a local server

The actions that currently run the code

  1. NPM run build, compile the relevant code
  2. Open the index.html code from live Server or directly from a browser to see what it looks like

But this operation is trivial, and we want to be able to compile and display files automatically when they change

Webpack provides several alternative ways to accomplish automatic compilation

  • webpack watch mode
  • Webpack-dev-server (common)
  • webpack-dev-middleware

3.1. Webpack watch

Webpack gives us watch mode:

  • In this mode, WebPack relies on all the files in the diagram, and if one of them is updated, the code will be recompiled
  • And we don’t need to run the NPM run build command manually

There are two ways to start watch:

  1. In the exported configuration, addwatch: true
  2. In the command to start Webpack, add --watchThe identity of the

Add a watch script to the scripts of package.json:

It can also be configured in webpack.config.js

3.2. Webpack – dev – server

The above method can listen for file changes, but does not automatically refresh the browser

We can use webpack-dev-server instead

Install: NPM install webpack-dev-server -d

Webpack-dev-server is not written to any output files after compilation. Instead, the bundle files are kept in memory and the Express server is enabled for the browser to read the resources, using memFS libraries internally

Module hot replacement (HMR)

HMR stands for Hot Module Replacement, which translates as Hot Module Replacement

Module hot replacement is the process of replacing, adding, and removing modules while the application is running without having to refresh the entire page

HMR improves the speed of development in the following ways:

  • Instead of reloading the entire page, update only what needs to change, which preserves the state of some applications and speeds up the refresh
  • If you modify the CSS and JS source code, it will be updated immediately in the browser, which is equivalent to modifying the style directly in the browser devTools

By default, Webpack-dev-server already supports HMR, so we just need to turn it on

Without HMR enabled, the entire page will refresh automatically after we modify the source code, using live reloading

Open the HMR

Modify webPack configuration:

We also need to specify which modules are updated to use HMR, otherwise the entire page will still be refreshed

Framework of HMR

When we are developing Vue/React projects and we want to make hot updates to components, will we write the API related to module.hot. Accpet as above?

In actual Vue development, we use VUe-Loader, which supports THE HMR of Vue components and provides out-of-the-box experience

In react development, there is react-refresh to adjust the React component in real time

The principle of HMR

How does HMR update only the contents of a specified template?

Webpack-dev-server creates two services: static resource service (Express) and Socket service (net.socket).

Express Server is responsible for serving static resources directly (packaged resources are directly requested and parsed by browsers)

HMR Socket Server, which is a Socket long connection:

  • One of the best benefits of a long connection is that the two sides can communicate after the connection is established (the server can send files directly to the client).
  • Json (manifest file) and.js (Update chunk) files are generated when the server detects that the corresponding module has changed.
  • These two files can be actively sent directly to the client (browser) via a long connection
  • The browser takes the two new files, loads them through the HMR Runtime mechanism, and updates them for the modified modules

HotOnly and host are configured

Host Indicates the host address. The default value is localhost

Localhost: Is essentially a domain name that will normally be resolved to 127.0.0.1

If you want access from other places, set it to 0.0.0.0

Localhost (127.0.0.1) 0.0.0.0

  • 127.0.0.1: Loop Back Address, which means the packet sent by our host is directly received by ourselves
    • Normal database packets are usually application layer – transport layer – network layer – data link layer – physical layer
    • The loopback address, which is directly obtained at the network layer, is not frequently accessed at the data link layer and physical layer
    • For example, when we listen on 127.0.0.1, hosts in the same network segment cannot be accessed through IP addresses
  • 0.0.0.0: Listen for all addresses on IPV4 and find different applications by port
    • For example, when we listen for 0.0.0.0, hosts in the same network segment are accessible by IP address

Port, open, compress

Port Sets the listening port. By default, it is 8080

Open Indicates whether to open the browser. The default value is false. Set true to automatically open the browser

Compress Specifies whether to enable Gzip compression for static files. The default value is false and can be set to true

3.3.vue.config. js configuration file

  1. Use vue inspect > output.js to see the default configuration of vue scaffolding.
  2. Scaffolding can be customized using vue.config.js at cli.vuejs.org/zh

3.4. Scaffolding Proxy

Proxy is a very common configuration option in our development that sets up proxies to solve cross-domain access problems

Then we can send the request to a proxy server first, proxy server and API server itself is not cross domain issues

We can do the following:

  • target: represents the destination address to be proxied to, such as/APIhttp://localhost:8888/api/abc
  • pathRewrite: By default, our/API is also written to the URL. If you want to delete it, you can use pathRewrite
  • secure: Does not accept HTTPS forwarding by default. You can set this parameter to false if you want to support HTTPS forwarding
  • changeOrigin: Indicates whether to update the host address of headers requested by the proxy

Methods a

Add the following configuration to vue.config.js:

devServer:{
  proxy:"http://localhost:5000"
}
Copy the code

Description:

  1. Advantages: The configuration is simple. When requesting resources, you can send them directly to the front-end server (8080)
  2. Disadvantages: Multiple proxies cannot be configured, and you cannot flexibly control whether requests go through proxies
  3. How it works: If the proxy is configured as above, when a request is made for a resource that does not exist in the front end, the request is forwarded to the server (matching the front end resource is preferred

Method 2:

Write vue.config.js to configure specific proxy rules:

module.exports = {
	devServer: {
      proxy: {
      '/api1': {// Matches all request paths starting with '/api1'
        target: 'http://localhost:5000'.// The base path of the proxy target
        changeOrigin: true.pathRewrite: {'^/api1': ' '}},'/api2': {// Matches all request paths starting with '/api2'
        target: 'http://localhost:5001'.// The base path of the proxy target
        changeOrigin: true.pathRewrite: {'^/api2': ' '}
      }
    }
  }
}
/* When changeOrigin is set to true, the host in the request header received by the server is: localhost:5000 Localhost :8080 changeOrigin Default value: true */
Copy the code

Description:

  1. Advantages: You can configure multiple proxies and flexibly control whether requests go through proxies
  2. Disadvantages: The configuration is cumbersome, and the prefix must be added when requesting resources

3.5. HistoryApiFallback

HistoryApiFallback is a very common attribute in development. Its main function isto solve the error of 404 returned when the SPA page is refreshed after a route jump

The default is false, but if set to true, the contents of index.html will be automatically returned when a 404 error is returned on refresh

If the value is of type Object, you can configure from in the rewrites property to match the path and determine which page to jump to

In fact, devServer implements historyApiFallback through the connect-history-api-Fallback library

See the connect-history-apI-fallback document

3.6. Resolve the resolve module

During development we have a variety of module dependencies, either from our own code or from third-party libraries

Resolve helps WebPack find the appropriate module code to introduce from each require/import statement

Webpack uses enhanced-resolve to resolve file paths

Webpack can resolve three file paths:

  • An absolute path
    • Since you already have the absolute path to the file, no further parsing is required
  • Relative paths
    • In this case, the directory in which the resource files that use import or require reside is considered a context directory
    • The relative path given in import/require is concatenated to generate the module’s absolute path
  • The module path
    • The resolve attribute retrits modules from all directories specified in modules. The default value is [‘node_modules’], so files are searched from node_modules by default
    • We can replace the initial module path with an alias, as explained below

Files are still folders

If it is a file:

  • If the file has an extension, package the file directly
  • Otherwise, the extensions option in Resolve will be used for file extension resolution

If it’s a folder

  • The files are searched in the folder in the order specified in the mainFiles configuration option in Resolve
    • The default value for resolve.mainFiles is [‘index’]
    • The extension is then resolved according to resolve.extensions

3.7. Extensions and Alias configurations

Extensions are automatically added when parsed to a file

  • The default is [‘.wasm’, ‘.mjs’, ‘.js’, ‘.json’]
  • So if we want to add add.vue or JSX or TS files to our code, we have to write the extension ourselves

Alias You can configure an alias

  • When the directory structure of our project is deep, or a file path may require.. /.. /.. / This path fragment
  • We can give some common paths an alias

3.8. Distinguish between development and production environments

Previously all webpack configurations were placed in the webpack.config.js file

In fact, some configurations are required in the development environment and some configurations are required in the build environment

We can distinguish their configurations for convenient maintenance and management

Add commands to package.json files to distinguish between development and production loading different files

Then we can create three files, also need NPM install webpack-merge -d merge configuration

  • webpack.comm.config.js
  • webpack.dev.config.js
  • webpack.prod.config.js
// webpack.comm.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { DefinePlugin } = require("webpack");
const { VueLoaderPlugin } = require("vue-loader/dist/index");

module.exports = {
  target: "web".entry: "./src/main.js".output: {
    path: path.resolve(__dirname, ".. /build"),
    filename: "js/bundle.js",},resolve: {
    extensions: [".js".".json".".mjs".".vue".".ts".".jsx".".tsx"].alias: {
      "@": path.resolve(__dirname, ".. /src"),
      js: path.resolve(__dirname, ".. /src/js"),}},module: {
    rules: [{test: /\.css$/,
        use: ["style-loader"."css-loader"."postcss-loader"],}, {test: /\.less$/,
        use: ["style-loader"."css-loader"."less-loader"],},// },
      {
        test: /\.(jpe? g|png|gif|svg)$/,
        type: "asset".generator: {
          filename: "img/[name]_[hash:6][ext]",},parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024,},},}, {test: /\.(eot|ttf|woff2?) $/,
        type: "asset/resource".generator: {
          filename: "font/[name]_[hash:6][ext]",}}, {test: /\.js$/,
        loader: "babel-loader"}, {test: /\.vue$/,
        loader: "vue-loader",}]},plugins: [
    new HtmlWebpackPlugin({
      template: "./public/index.html".title: "Ha ha ha ha.",}).new DefinePlugin({
      BASE_URL: "'/'".__VUE_OPTIONS_API__: true.__VUE_PROD_DEVTOOLS__: false,}).new VueLoaderPlugin(),
  ],
};
Copy the code
// webpack.dev.config.js
const { merge } = require("webpack-merge");
const commonConfig = require("./webpack.comm.config");

module.exports = merge(commonConfig, {
  mode: "development".devtool: "source-map".devServer: {
    contentBase: "./public".hot: true./ / host: "0.0.0.0",
    port: 7777.open: true.// compress: true,
    proxy: {
      "/api": {
        target: "http://localhost:8888".pathRewrite: {
          "^/api": "",},secure: false.changeOrigin: true,},},},});Copy the code
// webpack.prod.config.js
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { merge } = require("webpack-merge");
const commonConfig = require("./webpack.comm.config");

module.exports = merge(commonConfig, {
  mode: "production".plugins: [
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin({
      patterns: [{from: "./public".globOptions: {
            ignore: ["**/index.html"],},},],});Copy the code

Import file parsing

The rule we used to write entry files was./ SRC /index.js, but if the location of our configuration file becomes config directory, should we become.. / SRC/index. Js?

Js./ SRC /index.js, because the entry file is actually related to another property, context

Ontext is used to parse entry points and loaders.

  • The default should be the startup directory for WebPack

We can also pass in values in the configuration