Modular development

Modular development is one of the most important front-end development paradigms today, and modularity is just an idea

The following contents follow this directory structure:

1, modularization evolution process through the history, understand the value of the existence of modularization, as well as the problems to solve 2, modularization specification 3, commonly used modular packaging tools 4, based on modular tools to build modern Web applications 5, packaging tools optimization skillsCopy the code

Modular evolution process

From the code/file partition way to look at the early modular landing

  • File division mode

    Each separate file directory is a separate module, and modules have no separate scope space and pollute the global scope

  • Namespace mode

    Each module is packaged as a global object based on file partitioning, which reduces the risk of conflicts but does not solve them

  • IIFE executes the function immediately

    All the objects of the module are put into an anonymous function, and the objects that need to be exposed to the external are mounted to the global object, which realizes the concept of private members and ensures the security of private members

    The above three are early in the absence of tools and specifications, the implementation of modular way, the way has been agreed

The emergence of modular specifications

Why the modularity specification?

Why the modularity specification in the first place?

  • Different developers have different coding habits
  • Different projects have different Settings
  • Early modular loading is manually through the script tag outside the chain form, after a long time to increase the amount of maintenance, high difficulty

For these reasons, we need modular standards and module loaders to automate this work.

Commonly used modular packaging tools

What modular standards have emerged so far? Module standard analysis is as follows:

  • CommonJs specification

    • A file is a module
    • Each module has a separate scope
    • Exports members through module.exports
    • Load the module via the require function
    • Load modules in synchronous mode (not suitable for browser scenarios)
  • ADM specification (Asyncchronous Module Definition)

    • Asynchronous mode loading
    • Related library: require.js
    • You can return some members inside define, private space
    • Require, which automatically loads modules, only loads modules, and define is defined
    • Automatically create script tags and execute internal code
    • Most support this specification

    AMD specification:

    • Each module must be defined as define, as shown in Modular evolution/stage-5
    • The function takes three arguments in the order of the dependent array and the values of the exported members of the dependent array
    • The parameters are: module name, dependent array, and execution function

    AMD faults:

    • Relatively complex to use
    • When the module is carefully divided, file requests are frequent, resulting in performance deterioration
  • sea.js

    You can load files such as JavaScript with different sequential dependencies

    Now require is compatible with this approach

    It has now been eliminated

Modular scenario

  • node.js

    Use the CommonJs specification on the Node platform

  • The web browser

    ES6+ starts using the ESM (ECMAScript Module) specification

ESM features

As a new modular standard specification, what syntax and features are specified in the ESM?

How to use tools/solutions to solve compatibility problems in the runtime environment?

Features:

  • Automatically adopt strict mode, ignoring the ‘use strict’ header form
  • Each ESM runs in a separate private scope

For example, if two script tags have foo inside them, the second tag cannot fetch foo inside the first tag because of block-level scope. So you don’t have to worry about global pollution

  • The ESM requests external JS modules through CORS

To support this, return headers must be added to support cross-domain headers. Cors does not support file requests and must be accessed in the serve environment

  • The ESM’s Script tag delays script execution, as with the defer attribute
  • The type=module attribute is added to the script tag in the browser to execute code to ESM standards
  • ESM import and export functions include import and export

When an ESM file is exported using export, if default is not specified, the exported member must be specified for external use. If default is specified, the exported member can be directly used as a whole.

 / / there is no default
export const name = 'foo';
/ / when used
import { name } from './module.js';

/ / returns the default
const name = 'foo1';
export default name; Export default {name};
/ / when used
import ModuleData from './module.js';
Copy the code

Note: when exporting default, do not use var/let/const modifier

Matters needing attention:

The curly brackets following export default are object literals, because default is the specific content. The curly brackets following import are not destructions. When exporting a member, it exports a reference to the member. Both the base type and the reference type return a reference relationship, and the base data type is no longer copied.Copy the code

ESM import usage

1. In native Module, the end of the file can not be omitted, and the path must start with absolute or relative

import foo from './foo.js'
Copy the code

2. If you write the module name directly, it will be considered as a third-party module or directly use the CDN address

import loadsh from 'loadsh'

import jQuery from 'https://XXXXXXXX'
Copy the code

3. If no key is written after import, only the module will be executed without extracting any member information. This can be shortened to directly import ‘module path’.

import './foo.js' // Only the module will be loaded and executed, but the members will not be extracted
Copy the code

4. If you want to import all members, use * and you must alias as

import * as foo from './foo.js'
Copy the code

5. Import cannot be nested and cannot be dynamically imported. To dynamically import a module, you can use the import function as follows:

    import('./module').then(function(module) {
        console.log('module'.module);
    })
Copy the code

6. If both named member and default member are exported, you can rename default

import { default as foo, name } from './foo.js'
Copy the code

ESM exports import members

  • Import The result of an import is directly used as an export member of an export
export { foo, name } from './foo.js'

export { default as foo, name } from './foo.js'
Copy the code

Build modern Web applications based on modular tools

ESM- Browser environment Polyfill

  • It was only proposed in 2014, and it is not supported by early browsers, so it needs to use Polyfill compatibility, browser-es-module-Loader

Using this loader tool, you can convert Module code, but there is one exception: on browsers that support Module syntax, the code executes twice! What?

The reason it executes twice is that, on browsers that support module syntax, the contents of a Module are executed once they are loaded. The loader tool loads the code, transforms it, and executes it twice.

So is there a way around this? The answer is yes.

When a module is introduced with a script tag, the tag adds a nomodule attribute that tells the browser not to load polyfill files in a Module environment

However, this polyfill method is suitable for individual developers to test locally and is not recommended for deployment in an online environment. If you want to deploy online, it is advisable to compile and package the code before deploying it as a whole.

ESM in Node.js

  • Change the file extension to MJS for use in the Node environment
  • Command to add the experiment identifier parameter, following the file path and name, as in:
node --experimental-modules index.mjs
Copy the code
  • The built-in module of Node is compatible with the ESM member extraction method

    All members are exported individually and finally as a whole

ESM interacts with CommonJs

/ / commonjs module
module.exports = {
    foo: 'commonjs exports value'
}

// es module
import mod from './commonjs.js';
console.log(mod);
Copy the code

Validation works, but note that only default members can be exported in CommonJs, and members cannot be extracted

In contrast, modules cannot be loaded via require in CommonJs, which is not supported in native environments

ESM differs from CommonJs

You cannot use require, module, exports, __filename, __dirname in CommonJs

The reason is that these five functions are global functions exported by CommonJS. Although not directly available. However, the function can be simulated by means as follows:

  • __filename
// Get the file path through the fileURLToPath method of the built-in module URL. Commonjs is __filename
import { fileURLToPath } from 'url';
const currentMeta = import.meta.url;
const path = fileURLToPath(currentMeta);
console.log(path)
Copy the code
  • __dirname
// The directory address of the current module can be obtained by dirname,commonjs is __dirname
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const currentMeta = import.meta.url;
const path = fileURLToPath(currentMeta);
const filename = dirname(path);
console.log(path)
console.log(filename)
Copy the code

New VERSIONS of ESM-Node support this feature

In package.json, if “type” is set to “module”, all js suffixes in the project do not need to be changed to MJS, but in this case, the CommonJS module suffix should be changed to CJS

Optimization tips for packaging tools

ESM- Babel compatible solution

To use Babel, a dependency needs to be installed (Babel doesn’t directly shift our code, Babel is used as a plug-in to implement the function, a feature conversion needs to be installed a plug-in, preset is a set of feature plug-ins) :

yarn add @babel/node @babel/core @babel/preset-env --dev
Copy the code

Modify the Babel configuration after installation

{
  "presets": ["@babel/preset-env"]}Copy the code

If you don’t want to use this set. You need to install plug-ins for your own features to convert

conclusion

The modular development stage is very much detailed knowledge, but also with the actual work of the details of the point has a lot of embodiment, listen to and see only know, work constantly use, constantly encounter problems and solve the theory, will know why