js modular development history
The first stage
When the JavaScript language was first born, it was only used to implement some small effects on the page.
At that time, the JS used on a page might only be a few hundred lines of code.
In this case, some defects in the language itself are often intentionally ignored by everyone, because the size of the program is too small. As long as the developers are careful, they often do not cause any problems.
At this stage, there are no professional front-end engineers. Since there are too few things to do on the front-end, this part of the work is often completed by back-end engineers.
Major events in the first phase:
- In 1996, NetScape submitted the JavaScript language to a European standards-setting block ECMA (European Computer Manufacturers Association)
- In 1998, NetScape failed in the competition with Microsoft's browser IE and declared bankruptcy.
second stage
The emergence of ajax has gradually changed the role of JavaScript in browsers. Now, it can not only achieve small effects, but also interact with the server to change the data with a better experience
The amount of JS code began to gradually increase, from the first few hundred lines to tens of thousands of lines later, and the front-end program gradually became complex.
The pressure on back-end developers is gradually increasing, leading some companies to recruit professional front-end developers
But at this time, the treatment of front-end developers is far less than that of back-end developers, because the development tasks undertaken by front-end developers are relatively simple compared to back-end development. After just one month of intensive training, they can become a satisfactory Front-end development needs
The fundamental reason is that there are still several big problems that have not been solved in front-end development. These problems have seriously restricted the further expansion of the scale of front-end programs:
- The browser interprets and executes JS too slowly
- The client computer configuration is insufficient
- More code brings problems such as global variable pollution and dependency confusion.
The above three problems are like Achilles' heels, becoming the lingering shadow and original sin of front-end development.
At this stage, front-end development is in a very awkward position, wandering helplessly between the traditional development model and the separation of front-end and back-end.
Major events in the second phase:
- After IE browser dominated the market, it almost stopped updating
- The abortion of ES4.0 resulted in almost no changes in the JS language in 10 years
- ES5 was released in 2008, which only solved the bad situation of insufficient JS API.
The third phase
Time continued to move forward, and in 2008, Google's V8 engine was released, pushing the execution speed of JS to a new level, even comparable to back-end languages.
Moore's Law continues to ferment, and the configuration of personal computers begins to leap forward
Suddenly, the two major problems restricting front-end development were solved. At this time, only the last problem was still stubbornly resisting, namelyglobal variable pollution and dependency confusion Once the problem of a> is solved, the front-end can break through all obstacles, and the future is limitless.
As a result, front-end developers all over the world are having heated discussions in the community, trying to find a solution to this problem...
In 2008, a young man named Ryan Dahl was struggling with one thing. He needed to write a high-performance web service on the server side. The service had such high performance requirements that all existing web service products on the market were Can't meet demand.
After analysis, it was determined that if you want to achieve high performance, you must reduce threads as much as possible, and to reduce threads, you cannot avoid using asynchronous processing solutions.
At first, he planned to write it himself using C/C++ language, but the process was too painful.
Just when he was at a loss, the release of Google's V8 engine caught his attention. He suddenly discovered that isn't JS the best language for implementing web services? It is inherently single-threaded and based on async! With the support of the V8 engine, its execution speed can fully support a server. Moreover, V8 is released by the famous Google company. Google will continue to optimize V8. With such a good thing that saves money and effort, why should I write it myself?
Therefore, it was based on the open source V8 engine, made some modifications to the source code, and quickly completed the project.
In 2009, Ryan launched the web service project named nodejs.
From then on, JS took over the backend for the first time and was no longer a "toy" language that had to be attached to the browser.
It was also from this moment on that people realized that JS (ES) is a real language, which is executed depending on the running environment (runtime) (host program)
The birth of nodejs has brought the last problem in JS to the forefront, namelyglobal variable pollution and dependency confusionproblem a>
Until, nodejs is the server side. If this problem is not solved, module development will not be possible, and modular development is an essential content for all back-end programs.
After intense discussions in the community, a modular solution was finally formed, namely the famous CommonJS. This solution completely solved the problems of global variable pollution and dependency confusion.
As soon as this solution came out, it was immediately supported by nodejs. As a result, nodejs became the first platform to implement modularization for the JS language, laying a practical foundation for the rapid development of the front-end.
Major events that occurred during this stage:
- In 2008, V8 was released
- IE's market is gradually being eroded by firefox and chrome, and there is no way back now
- In 2009, nodejs was released and came with the commonjs modular standard
Stage 4
The emergence of CommonJS has opened up the minds of front-end developers
Since the backend can use modular JS, why can’t the browser, the old club of JS language, also do it?
As a result, some people began to think of ways to apply CommonJS to browsers.
But there are many difficulties here (explained in detail in the course)
There are always more solutions than difficulties. Some developers think that since it is difficult to apply CommonJS to browsers, why don't we redefine a modular standard ourselves? Do we have to use the CommonJS standard?
So soon, the AMD specification was released. It solved the same problems as CommonJS, but could better adapt to the browser environment.
Subsequently, the CMD specification was released, which improved the AMD specification.
These behaviors have received close attention from ECMA officials...
In 2015, ES6 was released, which proposed an official modular solution - ES6 Modular
Since then, modularity has become a unique property of JS itself. This language finally has the capital to compete with other languages and has become a formal language that can write large-scale applications.
At the same time, many developers and technology manufacturers have already foreseen the infinite potential of JS, so the following story came up
- Since JS can also write large-scale applications, it naturally needs a development framework to solve complex problems like other languages.
- Front-end development frameworks such as Angular, React, and Vue emerge
- The emergence of back-end development frameworks such as Express and Koa
- Various back-end database drivers appear
- To develop large-scale applications, the support of various practical third-party libraries is naturally indispensable.
- The emergence of npm package manager makes it extremely convenient to use third-party libraries
- Build tools such as webpack appear specifically for packaging and deployment
- Since JS can be placed in a server environment, why can't it be placed in other terminal environments?
- Electron released, can use JS language to develop desktop applications
- Technologies such as RN and Vuex are released, and mobile applications can be written using JS language
- Various small programs appear, and you can use JS to write small programs that are attached to other applications.
- There are currently many manufacturers committed to applying JS to various other terminal devices, eventually forming a large front-end ecosystem.
It can be seen that the emergence of modularization is the cornerstone of JS leading to large-scale applications. If you learn modularity well, you will have the basic skills to write large-scale applications.
CommonJS
In nodejs, since there is only one entry file (startup file), and developing an application will definitely involve the cooperation of multiple files, therefore, nodejs's demand for modularity is much greater than that of the browser.
Since nodejs was first released, there was no unified and official modular specification for the front end, so it chose to use CommonJS provided by the community as the modular specification.
Before learning CommonJS, first understand two important concepts: Export of module and module Import
Export of modules
To understand the export of modules, we must first understand the meaning of modules
What is a module?
A module is a JS file that implements some functions, hides its own internal implementation, and provides some interfaces for use by other modules.
The module has two core elements: Hide and Expose
What is hidden is its own internal realization
Exposed is the interface that is expected to be used by the outside world
Any normal modularization standard should hide all implementations in the module by default and expose the interface through some syntax or api calls.
The process of exposing the interface is the export of the module
Import of modules
When you need to use a module, the exposed part (exported part) of the module is used, and the hidden part can never be used.
When a module is used through a certain syntax or API, this process is called module import.
CommonJS specification
CommonJS usesexports to export modules, require to import modules
The specific specifications are as follows:
- If a JS file existsexports orrequire , the JS file is a module
- All code in the module is hidden code, including global variables and global functions. These global contents should not cause any pollution to global variables.
- If a module needs to expose some APIs for external use, it needs to be exported through exports, exports is an empty object, you can add any content that needs to be exported to this object
- If a module needs to import other modules, it is implemented through require, require< a i=4> is a function that returns the entire content exported by the module by passing in the path of the module
nodejs implementation of CommonJS
In order to implement the CommonJS specification, nodejs does the following processing for the module
- In order to ensure efficient execution, only necessary modules are loaded. nodejs will load and execute the module only when the require function is executed
Nodejs import module uses a relative path and must start with ./ or ../
- In order to hide the code in the module, when nodejs executes the module, it will place all the code in the module into a function for execution to ensure that global variables are not polluted. (function(){ //Code in module })( )
- In order to ensure the smooth export of module content, nodejs has done the following processing (function(module){ module.exports = {}; < /span> return< /span> module.exports; })()//Code in module exports = module.exports; var
- Initialize a value before the module starts executingmodule.exports = {}
- module.exportsThat is, the export value of the module
- In order to facilitate developers to export conveniently, nodejs declares a variable after initializingmodule.exports< a i=3>exports = module.exports, so you can directly use exports to export
- If the code in the module reassigns module.exports, then exports will not be associated with module.exports, and using exports again will be invalid.
- In order to avoid loading the same module repeatedly, nodejs enables module caching by default. If the loaded module has already been loaded, the previous export result will be automatically used.
The problem with browser-side modularity
How CommonJS works
When usingrequire(module path) to import a module, node will do the following two things (regardless of module cache):< /span>
- Find the native file through the module path and read the file content
- Put the code in the file into a function environment for execution, and use the value of module.exports after execution as the return result of the require function
It is these two steps that enable CommonJS to be well supported on the node side.
It can be considered thatCommonJS is synchronous, and you must wait until the file is loaded and the code is executed before it can continue to execute backwards
When the browser encounters CommonJS
When trying to put CommonJS on the browser side, we encountered some challenges
- To load a JS file, the browser needs to read it remotely from the server, and the efficiency of network transmission is far lower than the efficiency of reading local files in the node environment. Since CommonJS is synchronous, this will greatly reduce running performance
- If you need to read the content of a JS file and put it into an environment for execution, you need the support of the browser manufacturer, but the browser manufacturer is unwilling to provide support. The biggest reason is that CommonJS is a community standard and not an official standard.
new norm
Based on the above two reasons, browsers cannot support modularity
But this does not mean that modularity cannot be implemented in browsers
To achieve modularity in the browser, as long as the above two problems can be solved
The solution is actually very simple:
- Is loading JS remotely a waste of time? Just make it asynchronous and call a callback after loading is complete.
- Does the code in the module need to be placed in a function for execution? When writing a module, just put it directly in the function.
Based on this simple and effective idea, AMD and CMD specifications emerged, which effectively solved the problem of browser modularization.
However, with es6 modularization, amd and cmd are no longer used.
Introduction to ES6 Modularity
The ECMA organization referred to many community modular standards, and finally in 2015, with the release of the official modular standard for ES6, it later became ES6 modular
ES6 modularity has the following characteristics
- Use dependencypredeclaration to import modules
- Dependency delayed declaration (commonjs)
- Advantages: Can sometimes improve efficiency
- Disadvantages: Module dependencies cannot be determined at the beginning (more ambiguous)
- Dependency delayed declaration (commonjs)
-
- dependency predeclaration
- Advantages: Module dependencies can be determined at the beginning
- Disadvantages: sometimes less efficient
- dependency predeclaration
- Flexible multiple import and export methods
- Canonical path notation: all paths must start with ./ or ../
Basic import and export
Introduction of modules
NOTE: This part of the non-modular standard
Currently, browsers use the following method to introduce an ES6 module file
<script src="入口文件" type="module">
Basic export and import of modules
There are two types of module import and export in ES6:
- Basic import and export
- Default import and export
Basic export
Similar to exports.xxx = xxxx
There can be multiple basic exports, each must have a name
The syntax for basic export is as follows:
export declare expression
export let a=1;
ecport function test(){}
or
export {Ingredient name code}
let age=18;
let sex=male;
export{age,sex}
Since the basic export must have a name, it is required that the export content must be followed by declaration expression or Named symbol
Basic import
Since you are using dependency preloading, therefore, to import any other modules, the import code must be placed before all code
For basic export, if you want to import, use the code below
import {imported symbol list} from "Module path"
Pay attention to the following details:
- When importing, you can rename the imported symbols through the keywordas
- The symbols used when importing are constants and cannot be modified.
- You can use the * sign to import all basic exports to form an object, and the * must be renamed.
Default import and export
Default export
Each module, in addition to multiple basic exports, is also allowed to have a default export
The default export is similar to CommonJSmodule.exports. Since there is only one, there is no need to name it
The specific syntax is
export default Default exported data
or
export {默认弼传的数位as default}
Since only one default export is allowed per module, multiple default export statements cannot appear per module.
Default import
If you want to import the default export of a module, you need to use the following syntax
import Receive variable namefrom "Module path "
Similar to in CommonJS
var receives variable name = require("module path")
Since the variable name is defined by itself when imported by default, there is no alias.
If you want to import both the default and basic exports of a module, you can use the following syntax
import receives default exported variables, {receives basic exported variables} from "< /span>"Module path
Note: If you use the * sign, all basic exports and default exports will be aggregated into one object, and the default export will exist as the attribute default
Additional details about ES6 modularity
- Try to export immutable values
When exporting a content, try to ensure that the content is immutable (this is the case in most cases)
Because, although the imported content cannot be changed after importing, changes may occur inside the imported module, which will cause some unpredictable things to happen.
2. You can use unbound imports to execute some initialization code
If we just want to execute some code in a module without importing anything from it, we can use unbound imports:
import "model road diameter"
3. You can use binding and export to re-export content from another module
Sometimes, we may need to use one module to encapsulate multiple modules, and then selectively export the contents of multiple modules separately. This can be easily done using the following syntax
export {Bound identifier} from "Module path"