Webpack helps us pack the project into dist. It doesn’t mindfully pack all the files. It statically parsed the files we need to use, such as images that don’t have any reference anywhere.

1.require

const { stat,exists} = require('./index.js')
Copy the code

Require is run time loading, which actually loads the entire module, generates an object, and then reads the properties we call from the object, so you can’t do static optimization. The result of the code above is equal to

const _fs = require('./index.js')
const stat = _fs.stat
const exists = _fs.exists
Copy the code

Cannot use variables for parameter passing

require('./image/title.png')
Copy the code

A lot of times we want to write this introduction as dynamic

let imagePath = './image/title.png'
require(imagePath)
Copy the code

ImagePath knows exactly what path to import only at run time, but this is not allowed, probably syntactically correct, but WebPack can’t resolve the required path when building the package. Require needs to know at least which directory it is

let imageFullName = 'title.png'
1. require(`./image/${imageFullName}`)

let imageFullName = 'title'
2. require(`./image/${imageFullName}.png`)
Copy the code

Either way, WebPack can parse even if there is only one explicit directory, but this will result in the generated context module containing all the modules that might be used in that directory.

Synchronous & asynchronous loading

Asynchronous loading

require(['./mypage.vue'],resolve)
Copy the code

The special ‘require’ syntax will tell Webpack to automatically split your build code into multiple packages, which will be loaded via Ajax requests. When require takes the first argument to an array, it is loaded asynchronously, and then the second argument is a callback function that operates on the loaded module. When require takes the first argument to a string, it is loaded synchronously, and the second argument cannot be passed. Synchronous loading

var mypage = require('./mypage.vue')
Copy the code

2.require.context

Intuitively different from require, require.context introduces multiple modules. Require. context can be understood as creating its own context module. Context takes three parameters: 1. Directory File directories 2. UseSubdirectories Whether to find subdirectories 3. RegExp Matches the regular expression of the file

// Import all files with the js suffix in the model directory
require.context('./model'.true./.js$/)
Copy the code

Require. context can be understood as internally integrating all modules into a map, with the module’s path as its key

{
'./a.js':model,
'./b/f.js':model,
...
}
Copy the code

Require. context returns a function that takes a key argument and then returns the module corresponding to the key: 1. Resolve is a function that returns the module ID after the request is resolved. Keys is a function that returns an array of keys for all modules. Id is the id of the module contained in the Context Module

3.import

The import command is statically introduced, which is different from the dynamic introduction of require function. The loading is completed at the compilation stage, which is superior to require in terms of performance. However, if a large number of import commands are statically introduced into modules in the project, the initial package will become larger, which directly affects the loading time. Therefore, an import() function is proposed, which differs from one that is introduced statically and one that is introduced at run time. Because import() is executed at runtime, it can be placed anywhere. Import commands must be placed at the top of the module. Import () returns a Promise, which is loaded asynchronously

let imageUrl = ' '
import('./image/title.png').then(res= > {
  imageUrl = res
})
Copy the code

Import () can be used to address many performance optimizations for on-demand loading, such as on-demand loading of VUE routing components, and asynchronous loading of local component registrations

4. Use require.context to complete automatic project import

import a from "./a.js"
import b from "./b.js"
import c from "./c.js".Copy the code

In my work, I often encounter the above scenarios. The repetitive and regular operations that are divorced from business can be completely automated. Take vuEX modular design as an example

//index.js
import Vue from 'vue'
import Vuex from 'vuex'

import app from "./model/app.js"
import user from "./model/user.js".export default new Vuex.Store({
   modules:{ app, user, ... }})Copy the code

When the project application is very large, it will even be divided into dozens or hundreds of modules, and the code of the module will be very redundant. You can use require.context to import all modules at once

//index.js
import Vue from 'vue'
import Vuex from 'vuex'
import { resetModelName } from './util'

// Automatically import model
const requireModels = require.context('./model'.true./.js$/)
const storeModules = {}
requireModels.keys().forEach((item) = > {
    storeModules[resetModelName(item)] = requireModels(item).default
})

export default new Vuex.Store({
   modules: {... requireModels } })// util.js
/** * File path name conversion format: for example, './a/b.js' -> 'a_b' *@param {*} str String
 * @returns String* /
export function resetModelName(str) {
    str = str.replace(/.js$/g.' ')
    str = str.replace(/\.+\//g.' ')
    str = str.replace(/\//g.'_')
    str = str.replace(/\//g.' ')
    return str
}
Copy the code

Modules added later in the Model directory are automatically imported into the VUEX instance, as agreed upon. Or it can be encapsulated on top of this to make it configurable, providing configuration items such as naming rules, whether to find subdirectories, automatic voice switch, and so on. Simple convention rules or complex and powerful configuration rules can help standardize the entire front-end team.