Modularity is a kind of specification, a kind of constraint, this kind of constraint can greatly improve the development efficiency. Think of each JS file as a module, and each module is introduced in a fixed way and exposed in a fixed way. According to the idea of JS modularization, each module is combined according to its dependency relationship, and finally inserted into the main program.
B station modular video link: www.bilibili.com/video/BV18s…
www.bilibili.com/video/BV1e7…
Think no: segmentfault.com/a/119000001…
First, the introduction of JavaScript in HTML
1. Default
The following two scripts are introduced in HTML, which will be loaded and parsed from top to bottom, including module1.js and module2. During the parsing, page construction will be temporarily suspended.
<script src="module1.js"></script>
<script src="module2.js"></script>
Copy the code
2. The defer property — defer the script
When the script is introduced with the defer attribute, the script will execute without affecting the page construction. The browser will still download the module1.js and module2.js scripts immediately, but will wait until the page is constructed and parse the script from top to bottom, and module1.js will delay execution before module2.js.
<script src="module1.js" defer="defer"></script>
<script src="module2.js" defer="defer"></script>
Copy the code
3. Async property — Asynchronous scripts
When a script is introduced with the async property, the browser immediately downloads the file and parses it for execution. Page construction does not need to wait for the sample to download and execute, thus asynchronously loading other content. Module1.js may not be executed before module2.js, so the two modules cannot depend on each other.
<script src="module1.js" async></script>
<script src="module2.js" async></script>
Copy the code
Second, THE process of JS modularization
First, function mode
1. Definition: A module (.js) is defined as a function
2, import: in the page through import
3, problems: global variable pollution problem, after the introduction of modules in the page, the function name defined in the module and the variable name outside the function are global variables.
Object mode
1. Definition: A module (.js) is defined as an object
2, import: in the page through import
3. Problems: privatization of module variables. After the introduction of modules in the page, module objects are fully exposed in the global scope, and object (module) variables and functions can be accessed or even modified arbitrarily.
IIFE(Immediately execute function expression) mode
1. Definition: A module is defined as a closure, or a variable that gets the return value of the closure function
2. Expose: defined as a closure. The variable or method to be exposed is defined as a property of the Window object: window.m= XXX. Defined as a variable that gets the return value of the closure function, it goes into global scope when the script is introduced.
3. Import: Import in the page through , and then use “m” to expose the content of the module.
4. Existing problems: solved the problem of global scope pollution and variable privatization (to expose the variable name of the content and not exposed variables are not accessible), the existing problem is module dependency and module expansion problem.
Define and expose modules:
Function (){uname="Alice"; function sayName(){ console.log("I am "+uname); } window.m=sayName; })(function(){uname="Cindy"; function sayName(){ console.log("I am "+uname); } return sayName; }) ()Copy the code
HTML code (imported)
<script src="module1.js"></script>
<script type="text/javascript">
m();
</script>
Copy the code
IIFE enhanced mode (extension immediately execute function expression)
This mode is actually based on IIFE to pass parameters to the closure function, based on which you can pass in its dependent module, can also extend the original module;
1. Definition: A module is defined as a closure and the dependent module is passed as an argument to the closure function.
2. Exposure: same as above
Import: Dependency modules must be introduced before custom closure modules. In the following example, the jQuery library must be introduced before modue2.js is introduced because it is an input parameter to and used in the code for the module2 module, which it depends on.
4. Problem: Strict guarantee of script loading sequence, fuzzy dependency relationship.
Define and expose modules:
Function (window,$){uname="Cindy"; function(window,$){uname="Cindy"; function sayName(){ console.log("I am "+uname); } $("body").css("background-color","pink"); window.m=sayName; })(window,jQuery)Copy the code
The HTML code
The < body > < script SRC = "https://cdn.bootcdn.net/ajax/libs/jquery/1.8.0/jquery-1.8.0.js" > < / script > < script src="module2.js"></script> <script type="text/javascript"> m(); </script> </body>Copy the code
Modularization process at this point, you can realize the privatization of variables in modules, export and import on demand, module dependency issues. However, the script loading sequence must be strictly guaranteed. Many scripts have been downloaded for a long time, which may send too many requests and consume bandwidth. And the fuzzy dependency relationship leads to poor maintainability.
JS modular specification
Now the modularization process is back-end first, with CommonJS back-end modularization, then AMD, then CommonJS front-end modularization, and finally ES6 specification.
A, AMD
AMD is the front-end modular specification, which is based on the IIFE pattern. Module loading is asynchronous. This is a good example of module dependency, in the index.html page only need to import a JS file, no multiple requests problem.
1. Define and expose: Each file is treated as a module, defined as follows, and the contents of the return are what to expose.
-
Define modules that have no dependencies
Define (function(){return module})
-
Define a module that has no dependencies. The first parameter specifies the module to depend on as an array. The second module is a function whose arguments correspond to the modules in the array.
Define ([‘module1′,’module2’],function(m1,m2){return module})
2. Introduction: the module needs to be loaded with require.js
Require (['module1','module2'],function(m1,m2){use m1/m2})Copy the code
Write the code using the AMD specification modularization as follows
Define and expose modules:
Math.js: modules with no dependencies
define(function(){ var add=function(x,y){ return x+y; } return{myadd:add, // expose an object}});Copy the code
Tool. js: relies on custom main.js module and third-party jquery module, jquery source code, support amd specification, and custom module named jquery
define(['math','jquery'],function(math,$){ var show=function(){ alert("done it! Look at me!" + math.h myadd (10, 30)) $(" body "). The CSS (' background ', 'deeppink'); } return{ myshow:show } });Copy the code
Introduction module:
Main.js: entry file, which imports all modules to be loaded
// require(['math','tool'], function (math,tool){alert(math.myadd(1,3)); tool.myshow(); }); // Configure the path so that the module does not need the full path when loading, Require. config({paths:{"math":"modules/math", "tool":"modules/tool", "Jquery ":"libs/jquery-3.6.0"Copy the code
Index.html: specifies that the entry file to be loaded by require.js is mian
<! Every HTML file should have an entry file, which manages all the.js code used in the current.html page. 3. All subsequent.js code extensions need to be omitted. --> <script src="js/libs/require.js" async data-main="js/main.js"></script>Copy the code
Second, the CommonJS
This is the back-end modularity specification on which Node.js is written. If we want to use this specification on the front end, we have to help compile packaged code with libraries that handle CommonJS syntax, such as Browserify. It recursively analyzes all the require() calls in the code, and then builds a buddle.js file that we just need to pass through on the page
browserify will recursively analyze all the require() calls in your app in order to build a bundle you can serve up to the browser in a single
Define and expose: Each file is an exports object exposed as a module.
- Module. exports=value (Overwrites exports, overwrites what is exposed)
- Exports. XXX =value (exports. XXX =value)
3, import: require(XXX) : if it is importing a third-party library, XXX is the module name, if it is custom module, XXX is the file path name;
Write code using CommonJS specification modularization as follows:
Modules defined and exposed:
module1.js
Module. exports={MSG :"module1 hello word", foo(){console.log(this.msg); }}Copy the code
module2.js
Module.exports =function(){console.log("module2 hellow world")} //module.exports=value, exports=function(){console.log("module2 hellow world")}Copy the code
module3.js
//exports. XXX =value, add attribute to exports.foo=function(){console.log('module3 foo'); }; exports.bar=function(){ console.log('module3 bar'); }; Exports. Arr = [1,2,2,3,4,4,4,5,]Copy the code
Import modules: (back end, app.js file: entry file, this file imports all modules to be loaded)
// introduce custom module let m1=require('./modules/module1') // object let m2=require('./modules/module2') // function let Let uniq=require('uniq'); m3=require('./modules/module3') / / function https://www.npmjs.com/package/uniq m1. Foo (); m2(); m3.foo(); m3.bar(); var arr=uniq(m3.arr); console.log(arr);Copy the code
Importing modules :(front end, index.html)
In addition to the above code for module1.js, module2.js, module3.js, app.js (path: js/ SRC /app.js, entry file), something else needs to be done:
-
Download and install browserify (global & local) :
npm install browserify npm install browserify –save-dev
-
Browserify compiles the packaged code
browserify js/src/app.js -o js/dist/bundle.js
Then, import the packaged buddle.js file directly from index.html
<script src="./js/dist/bundle.js"></script>
Copy the code
ES6 module specification
The ES6 module specification is the most popular module specification on the front end and is much simpler to define, expose, and introduce modules than AMD or CommonJS. It’s just a little extra work, not only converting ES6 to ES5 using a library like Babel for browser recognition, but also compiling the packaged code using a library like Browserify. The use of browserify compilation package is the same as above, and Babel is used as follows:
-
Install Babel
npm install babel-cli browserify -g npm install babel-preset-es2015 –save-dev
-
ES6 to ES5 Default Settings: config. Babelrc file (added if none)
{ “presets”: [“es2015”] }
-
Babel compiles ES6 to ES5 code (including commonJS syntax), console input (js/ SRC is the directory where all module files are located)
babel js/src -d js/lib
Here are the definitions, exposures, and references to ES6 modularity
1. Define and expose: export, including separate exposure, unified exposure and default exposure
Import *** from “module path/third party library name
Write code using ES6 specification modularization as follows:
Modules defined and exposed:
module1.js
// Expose any data type of function, variable, Export function foo(){console.log("foo module1")} export function bar(){console.log("bar module1")} export Let arr = [1, 2, 3, 4]Copy the code
module2.js
Function fun1(){console.log(" fun1module2 ")} function fun2(){console.log(" fun2module2 ")} export {fun1,fun2} function fun2(){console.log(" fun2module2 ")} export {fun1,fun2} // Package as an object to exposeCopy the code
module3.js
// Default exposure can be exposed to any data type, and the data received is the same as the data received. //export default value export default {MSG :"HELLO WORLD MODULE3", Show (){console.log(" default exposed "+this.msg)}}Copy the code
Introduction module:
Mian.js (entry file)
import {foo,bar} from "./module1"; Import {fun1,fun2} from "./module2"; import m3 from "./module3" ; foo(); bar(); fun1(); fun2(); m3.show();Copy the code
Index.html: Browserify is packaged and introduced into the buddle.js file
<script src="./js/dist/bundle.js"></script>
Copy the code
As you can see, the ES6 modular specification is fun to use, but the need to rely on various libraries to help work is tired, we need to rely on more powerful tools to help with syntax conversion and compilation packaging work, so WebPack comes into play.
Fourth, the webpack
Webpack is a front-end resource builder that can do a lot of work, but I’ll focus on how it can help with some of the syntactic conversions and compilation packages under the ES6 specification.
Using the ES6 modularity specification, define modules module1.js, module2.js, module3.js and the entry file index.js as above (in the SRC directory).
1. Initialize the project and install Webpack and WebPack-CLI
npm init
npm install webpack webpack-cli --save-dev
Copy the code
2. The console enters the following command: package the entry file into the build/main.js file.
webpack ./src/index.js -o ./build --mode=development
Copy the code
Alternatively, the webpack.config.js configuration entry and exit are as follows, and the console enters the Webpack directive
Const {resolve}=require('path') module.exports={// entry:'./ SRC /index.js', // output:{filename:"main.js", Path :resolve(__dirname,'build')}}Copy the code
Index.html is introduced into the packaged main.js
<script src="./build/main.js"></script>
Copy the code
As you can see, there is a webPack that can do all the work that you need to do to download Babel and Browserfily in one stop. You just need to focus on writing JS code, and webPack can do a lot more work, so engineering is important on the front end.