Dynamic loading and packaging of Web pack

webpack code splitting

webpack has two ways to organize module dependencies, synchronous and asynchronous. Asynchronous dependency is used as the segmentation point to form a new block. After optimizing the dependency tree, each asynchronous block is packaged as a file.

Context module

There are six types of context modules: sync / lazy / lazy once / eager / weak / sync weak

  • sync: directly package the current file, load and execute synchronously

  • Lazy: generate a lazy loadable chunk for each module imported by import()

  • Lazy once: generate a lazy loadable chunk that can satisfy all import() calls

    This chunk will be obtained on the first import() call, and then import() will use the same network response. Note that this pattern only makes sense in dynamic statements. For example: import(./locales/${language}.json), which may contain multiple requested module paths.

  • eager: separate chunk files will not be separated, but promise will be returned. The code will be executed only when promise is called. It can be understood that the code is loaded first, but we can control the delay in executing this part of the code.

    This module prevents webpack from generating additional chunks. All imported modules are included in the current chunk, so there is no need to send additional network requests. It still returns a promise, but it will be automatically resolved. The difference between dynamic import using eager mode and static import is that the whole module will be executed only after import() is called.

Example: the current Vue file is home Vue, the same level menu has a folder pages, which contains three files a.vue, b.vue and c.vue

// Package home, a, B and C into different chunk s
import('./pages/' + pageId)

// Turn Home into a chunk, and a/b/c is uniformly packaged into a chunk
import(/* webpackMode: "lazy-once" */ './pages/' + pageId)

// Package home, a, B and C into a chunk, and the code in a/b/c can only be executed after import (not when the chunk is loaded)
import(/* webpackMode: "eager" */ './pages/' + pageId)

Note: even if a file in pages is not referenced, it will be packaged!

The actual path requested through the context component is the relative path relative to the specified directory; Here, the path relative to the '/ pages' context is'/ a.vue’, ‘./ b.vue’, ‘./ c.vue’

How to generate contextModule

Require (expression)

require(./locale/${language}.js) will package the matched files

require.context() function

  (directory: String),
  (includeSubdirs: Boolean) /* Optional. The default value is true */,
  (filter: RegExp) /* Optional. The default value is / ^. \ /. * $/, All documents */,
  (mode: String)  /* Optional, 'sync' | 'eager' | 'weak' | 'lazy' | 'lazy once', and the default value is' sync ' */

A context module will export a (require) function, which can receive a parameter: request.

This export function has three attributes: resolve, keys, and ID.

  • resolve is a function that returns the module id obtained after the request is parsed.

  • keys is also a function that returns an array consisting of all requests that may be processed by this context module

  • You may use the module id hot. It will be used when accepting

    With the current file index JS peer directory modules has AAA / index JS and BBB / index JS two files

    const modulesFiles = require.context('./modules', true, /index.js$/)
    console.log('modulesFiles:', modulesFiles)
    // ƒ webpackContext(req) {
    //     var id = webpackContextResolve(req);
    //     return __webpack_require__(id);
    // }
    console.log('modulesFiles.keys:', modulesFiles.keys()) // ['./aaa/index.js', './bbb/index.js']
    console.log('modulesFiles.resove:', modulesFiles.resolve('./bbb/index.js')) // ./src/store/modules/bbb/index.js
    console.log('modulesFiles.id:', modulesFiles.id) // ./src/store/modules sync recursive index.js$
    export const modules = modulesFiles.keys().reduce((res, modulePath) => {
      const pathName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
      const moduleName = pathName.replace('/index', '')
      const module = modulesFiles(modulePath)
      const dModuleName = module.default.name || ''
      console.log('modulePath:', modulePath)
      console.log('moduleName:', moduleName)
      console.log('module:', module)
      res[dModuleName || moduleName] = module.default
      console.log('res:', res)
      return res
    }, {})

import() function

/* webpackInclude: /\.json$/ */
/* webpackExclude: /\.noimport\.json$/ */
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */ /* 'eager' | 'weak' | 'lazy' | 'lazy-once',The default value is' lazy ' */
/* webpackPrefetch: true */
/* webpackPreload: true */
/* webpackIgnore: false */ /* Set webpackIgnore to true to avoid code splitting */

require.ensure() function

require.ensure() has been replaced by import()

Dynamic loading with environment variables

When the code is running, by judging the environment variables (e.g. process.env.NODE_ENV = = 'production'), it will only package the requests for logical branches that meet the judgment conditions!!!;

export function getBaseUrl () {
  if (process.env.NODE_ENV === 'production') {
    return '/performance/'
  } else {
    const requireHostFiles = require.context('@/api', false, /devHost.js$/)
    return requireHostFiles.keys().includes('./devHost.js') ? requireHostFiles('./devHost.js').devHost : require('@/dev.host.js').devHost

If process env. NODE_ Env = = = 'production', only pack '@ / prod.host js’

Otherwise, the directly subordinate files under '@ / api' will be packaged to meet / devhost JS $/ regular file, and '@ / dev.host js’

Keywords: node.js Front-end Vue.js Webpack

Added by discosuperfly on Fri, 11 Feb 2022 15:12:12 +0200