当前位置:网站首页>After reading this article, I understand a lot of webpack scaffolding

After reading this article, I understand a lot of webpack scaffolding

2020-11-06 01:17:00 :::::::

2018.3.1 more :

I like it · Wechat mall (base Hangzhou ) Department Recruitment front end , The nearest front end hc There are more than a dozen , Kneel down and beg the boss to throw his resume , I'll just push it in and feed back the progress in real time , Interested email lvdada#youzan.com, Or hook up with me through wechat wsldd225 Know more

You like the open source component library ·zanUI


Division webpack Various ways to configure files

( One )

Write your configuration information to multiple distributed files , And then in the webpack When using --config Parameter specifies the configuration file to load , Configuration files make use of moduleimports export . You can webpack/react-starter I see that this hair method is used .

// webpack  The configuration file 

|-- webpack-dev-server.config.js
|-- webpack-hot-dev-server.config.js
|-- webpack-production.config.js
|-- webpack.config.js
// npm  command 

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev-server": "webpack-dev-server --config webpack-dev-server.config.js --progress --colors --port 2992 --inline",
    "hot-dev-server": "webpack-dev-server --config webpack-hot-dev-server.config.js --hot --progress --colors --port 2992 --inline",
    "build": "webpack --config webpack-production.config.js --progress --profile --colors"
  },

( Two )

Call a third party webpack Tools , Using its integrated api, Easy to carry out webpack To configure .HenrikJoreteg/hjs-webpack This repo That's what it does .

var getConfig = require('hjs-webpack')


module.exports = getConfig({
  // entry point for the app
  in: 'src/app.js',

  // Name or full path of output directory
  // commonly named `www` or `public`. This
  // is where your fully static site should
  // end up for simple deployment.
  out: 'public',

  // This will destroy and re-create your
  // `out` folder before building so you always
  // get a fresh folder. Usually you want this
  // but since it's destructive we make it
  // false by default
  clearBeforeBuild: true
})

( 3、 ... and ) Scalable webpack configurations

ones that can be reused and combined with other partial configurations

Maintain configuration in a single configuration file , But distinguish between good conditional branches . Call different npm Set different environment variables during command , And then match... In the branch , Return to the configuration file we need .

The benefits of this can be managed in a single file npm Logic of operation , And you can share the same configuration .webpack-merge This module can be used to merge configuration .

const parts = require('./webpack-config/parts');

switch(process.env.npm_lifecycle_event) {
  case 'build': 
    config = merge(common, 
      parts.clean(PATHS.build),
      parts.setupSourceMapForBuild(),
      parts.setupCSS(PATHS.app),
      parts.extractBundle({
        name: 'vendor',
        entries: ['react', 'vue', 'vuex']
      }),
      parts.setFreeVariable('process.env.NODE_ENV', 'production'),
      parts.minify()
      );
    break;
  default: 
    config = merge(common, 
      parts.setupSourceMapForDev(),
      parts.devServer(), 
      parts.setupCSS(PATHS.app));
}
// minify example
exports.minify = function () {
  return {
    plugins: [
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false,
          drop_console: true
        },
        comments: false,
        beautify: false
      })
    ]
  }
}

Automatic refresh in development environment

webpack-dev-server

webpack-dev-server stay webpack Of watch On the basis of the server .

webpack-dev-server It's a development server running in memory , Support advanced webpack characteristic hot module replacement. This is for react vue This kind of component development is very convenient .

Use webpack-dev-server Command to turn on the server , coordination HMR And can achieve code change browser local refresh ability .

hot module replacement

Hot Module Replacement (HMR) exchanges, adds, or removes modules while an application is running without a page reload. When the application is running hmr The mechanism can be modified 、 add to 、 Or remove the corresponding module , Instead of refreshing the entire page .

hmr Mechanism for single page applications .

To achieve hmr Mechanism , Need to cooperate with webpack-dev-server The server , The server itself monitors watch The ability to change files , And open HMR Options , Just add watch The ability of modules to change . This is a HMR The basis for the mechanism to work .

from webpack Compiler perspective

Every time you modify a module ,webpack It will generate two parts , One is manifest.json, Another part of this update is about the completion of the module chunks.manifest.json What's in it is chunk Before and after the change hash value .

From the compiler webpack From the point of view of hmr Raw materials . For subsequent use .

From the perspective of modules

When the module changes ,webpack It will generate two parts of the basic file mentioned before , But when to apply the changed module to app In the middle ? Here we need to write in the application code handler To receive module change information . But it can't be written in all modules handler Well ? Here we use the message bubble mechanism .

Pictured A.js、C.js There's no correlation hmr Code ,B.js Related hmr Code , If c The module has changed ,c The module does not hmr, Then it will bubble a、b modular .b The module captures the message ,hmr The runtime will perform some operations accordingly , and a.js You can't capture information , It will bubble to entry.js, And once there's a bubbling entry block , This represents this time hmr failed ,hmr Will be downgraded for the entire page reload.

from HMR The angle of operation

HMR The runtime is a number of related operations api, The runtime supports two methods : checkapply.

check launch HTTP Request to get updated manifest, And some updated chunk.

Setting of environment variables

var env = {
    'process.env.NODE_ENV': '"production"'
}
new webpack.DefinePlugin(env)

Notice that there is an extra double quotation mark between single quotation marks why?

as well as webpack.DefinePlugin Principle of plug-in ?

When developing, I want to write a lot of code that only appears in the development environment , For example interface mock etc. , stay build The code doesn't exist after the command .

This is for plug-ins or frameworks 、 Component development is very helpful .vue,react I'll do it all the time . Can be in these frames of dev Patterns provide a lot of useful tips .

Package file segmentation

Why split the packaged file ?

For a single page application project , There are business code and third party code , Business code changes frequently , Third party code generally changes less times , If you need to change the business code every time, the user will js Download the files again , Not desirable for loading performance , So generally speaking, we will divide the code into business code and third-party code and package them separately , Although there is one more request file , Increased some network overhead , But compared to the browser can cache files , These costs are negligible .

We are entry It defines app entrance , The corresponding business logic is encapsulated in this entry file , If we want third-party code to be independent , We're going to add another entrance , We are used to using vendor The name .

// app.js

require('vue');
require('vuex');
// webpack.config.js


entry: {
    app: 'app/app.js',
    vendor: ['vue', 'vuex'],
  },

vendor The parameters of the entry are passed in the form of an array , This is a very convenient way to inject multiple dependencies , And it can package multiple dependencies into one chunk in . And you don't have to manually create a live entry file .

This is equivalent to :

// vendor.js

require('vue');
require('vuex');

// app.js

require('vue');
require('vuex');
// webpack.config.js


entry: {
    app: 'app/app.js',
    vendor: 'app/vendor.js',
  },

But it's just a statement that vendor It's just the entrance , about app This entrance says , There will still be vue and vuex rely on , And new entrances vendor The packaged files are also available vue and vuex Two dependencies . The module dependencies are shown in the following figure .

there A Can represent vue rely on , Finally, the generated package file is two parallel files , And they all contain vue Dependence .

You need to introduce CommonsChunkPlugin plug-in unit

This is a pretty complex plugin. It fundamentally allows us to extract all the common modules from different bundles and add them to the common bundle. If a common bundle does not exist, then it creates a new one.

It's a pretty complicated plug-in , Its basic function is to allow us to extract the same module from different packages , Then add these modules to the public package file . If the public package does not exist , Add a new . At the same time, this plug-in will also run time (runtime) Transfer to the public chunk In the package file .

plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    names: ['vendor', 'manifest']
  })
]

there name You can choose existing blocks , Here we choose vendor block , Because we are going to vendor Block as an entry point for managing third-party code .

and names Pass in an array , The array contains two trunk name, Express CommonsChunkPlugin The plug-in will execute this method twice , For the first time, public third-party code was moved away to vendor In blocks of , This process also mentioned before will run time runtime It's also moving to vendor In block , The second execution will run time runtime Pull out and transfer to manifest In block . This operation solves the caching problem .

This kind of treatment , Finally, it will generate 3 A package file chunk,app.js It's business code ,vendor It's public third-party code ,manifest.js It's the runtime .

chunk type The type of block is revealed

webpack1.0 In the introduction of the official website chunk The type is rather awkward to read chunk type, So I'll read it here .

chunk yes webpack One of the most basic concepts in , And chunk Often with entry To confuse . stay 「 Package file split section 」 We define two entrances entry point -- app and vendor, And through some configuration ,webpack The final package file will be generated , In this example, the final generated file is app.js 、 vendor.js 、 manifest.js. These files are called blocks chunk.

entry & chunk It can be simply understood as an entrance 、 An outlet

In the official 1.0 In the document webpack Of chunk There are three types of :

  1. entry chunk Entrance block
  2. normal chunk Common block
  3. initial chunk The initial block

entry chunk Entrance block

entry chunk Entrance block It cannot be understood literally as a file compiled from an entry file , Introduced by the official website

An entry chunk contains the runtime plus a bunch of modules

It can be understood as containing runtime Blocks at run time can be called entry chunk, Once there is a runtime (runtime) Of entry chunk Lost runtime , This piece will turn into initial chunk.

normal chunk Common block

A normal chunk contains no runtime. It only contains a bunch of modules.

Ordinary blocks do not contain runtime runtime, It only contains a series of modules . But when the application is running , Ordinary blocks can be loaded dynamically . Usually with jsonp The packaging method of loading . and code splitting The main use is the common block .

initial chunk The initial block

An initial chunk is a normal chunk.

The official response to initial chunk The definition of is very simple , The initial block is a regular block , Just like a normal block, it also doesn't contain the runtime runtime, The difference is that the initial block is calculated during the initial loading process . In introducing the entrance block entry chunk I also introduced , Once the entry block loses its runtime , It becomes the initial block . This shift is often made by CommonsChunkPlugin Plug-in implementation .

Example explanation

Or take 「 Package file segmentation 」 Code for example ,

// app.js

require('vue');
require('vuex');
// webpack.config.js


entry: {
    app: 'app/app.js',
    vendor: ['vue', 'vuex'],
  },

Not used CommonsChunkPlugin Before plug in , Two entry They were packed into two chunk, And these two. chunk Each contains the runtime , This is called entry chunk Entrance block .

And once used CommonsChunkPlugin plug-in unit , Runtime runtime It was eventually transferred to manifest.js file , At this point, the final package generated three chunkapp.js 、 vendor.js 、 manifest.js,app.js、vendor.js lost runtime From the entry block to the initial block .

code splitting

As mentioned earlier, partitioning dependencies helps browser caching , Improve user load speed , But as business complexity increases , The amount of code is always a problem . It's time to normal chunk The dynamic loading ability of ordinary blocks is .

It allows you to split your code into various bundles which you can then load on demand — like when a user navigates to a matching route, or on an event from the user. code splitting Allows us to split the code into different packages that can be loaded on demand , When the user navigates to the corresponding route , Or when the user triggers an event , Load the corresponding code asynchronously .

We need to manually add some segmentation points to the business logic , After indicating the event logic here, the code block is loaded asynchronously .

// test
window.addEventListener('click', function () {
  require.ensure(['vue', 'vuex'], function (require) {

  })  
})

This code shows that when the user clicks , Asynchronously request a js file , This file contains vue vuex Dependence .

After packaging, a package file will be generated according to the information of manual segmentation points , It's the first line in the picture 0 Opening file . This file is also the file loaded asynchronously .

Here's the previous one vue project , use code splitting After pulling out several routes and loading them asynchronously , File by 212kb Reduced to 137kb, In the same way, style files are also made by 58kb Reduced to 7kb. For the first screen rendering , Performance will increase a lot .

If you need to communicate, you can contact me on Weibo Dada's Siamese Cat

Reference resources :

Participation of this paper Tencent cloud media sharing plan , You are welcome to join us , share .

版权声明
本文为[:::::::]所创,转载请带上原文链接,感谢