走向Node与Webpack 之路 - CommonJS 模块化
走向Node与Webpack 之路 - CommonJS 模块化
1. 参考资料
CommonJS规范(推荐 - 阮一峰写的)
官方网站 (看半天,不知道干啥!)
CommonJS 是什么 ? (有些晕)
2. 基本环境
- node v4.5.0
- npm v4.2.0
这里基本环境安装配置就不说了,自己查找资料。
使用webstrom ,使用 node 记得enable ,写相关命令的时候,才会提醒显示:
如图:我的是已经打开的
3. 认识
无论是node
应用模块,还是webpack
配置 ,均是采用CommonJS
模块化规范。
Example :
example.js
/**
* Created by yuan on 2/21/2017.
*/
var x = 1;
var addX = function (value) {
return value + x;
}
module.exports.x = x; #对外提供值
module.exports.addX = addX; #对外提供函数
example-test.js
/**
* Created by yuan on 2/21/2017.
*/
var example = require('./example.js') #加载模块
console.log(example.x) #调用value
console.log(example.addX(12)); #调用函数
执行 : node xxx.js 执行 js 文件
D:\webworkspace\webpack-demo\commond>node example1-test.js
1
13
规范:
- 每个
js
文件就是一个模块,有自己的作用域 ; - 每个
js
文件定义的函数,变量,类都是私有的; - 每个模块的运行,不会污染全局作用域 ;
- 每个模块可以多次加载,但只会在第一次加载时运行一次,然后结果就缓存了;重新运行模块,需要清除缓存;
- 所有模块的加载顺序不定,按照被使用的顺序加载;
- require : 加载模块
- module.exports : 对外提供接口
3.module
所有的模块都是一个module对象,代表当前模块
Example :
引入jquery , 打印当前module ;
- npm install jquery -g : 安装jquery
D:\webworkspace\webpack-demo\commond>npm install jquery -g
C:\Users\yuan\AppData\Roaming\npm
`-- jquery@3.1.1
- 配置 package.json dependencies 依赖
"dependencies": {
"jquery": "^3.1.1",
}
- example.js
/**
* Created by yuan on 2/21/2017.
*/
var jquery= require('jquery');
exports.$ = jquery;
console.log(module);
- 执行
D:\webworkspace\webpack-demo\commond>node example2.js
Module {
id: '.', #模块识别,通常是模块的绝对路径文件名
exports: { '$': [Function] },#模块对外输出的接口
parent: null, # 返回对象,表示调用该模块的模块
filename: 'D:\\webworkspace\\webpack-demo\\commond\\example2.js', # 绝对路径的模块名
loaded: false, # 表示是否加载完成
children: # 表示该模块依赖的其他模块
[ Module {
id: 'D:\\webworkspace\\webpack-demo\\node_modules\\jquery\\dist\\jquery.js',
exports: [Function],
parent: [Circular],
filename: 'D:\\webworkspace\\webpack-demo\\node_modules\\jquery\\dist\\jquery.js',
loaded: true,
children: [],
paths: [Object] } ],
paths:
[ 'D:\\webworkspace\\webpack-demo\\commond\\node_modules',
'D:\\webworkspace\\webpack-demo\\node_modules',
'D:\\webworkspace\\node_modules',
'D:\\node_modules' ] }
(1)认识module
- id : 模块识别,通常是模块的绝对路径文件名
- exports : 模块对外输出的接口
- parent : 返回对象,表示调用该模块的模块
- filename : 绝对路径的模块名
- loaded : 表示是否加载完成
- children : 表示该模块依赖的其他模块
(2)module.exports
module.exports 当前模块对外输出的接口,对外提供变量;在每个模块中默认实现了
var exports=module.exports;
Example 1 :
/**
* 返回x平方与y平方和
* @param x
* @param y
* @returns {number}
*/
function add(x, y) {
return x * x + y * y;
}
// exports.add = add; // 对外提供add函数
// module.exports.add = add; //对外提供add函数
结果:
上面两种写法,实现的效果是一样的;建议使用 module.exports 来做,我觉得代码清晰。
Example 2 :
//ok
exports.hello = function () {
console.log('hello node!')
};
//error1 : 该exports 赋值 就和 module.exports 没有了联系!
exports = function (x) {
console.log(x);
};
//error2 :
module.exports = 'hello commonJS';
结果:
注意: 不可以对exports 或 module.exports 直接赋值,不然exports 就和 module 本身的exports 没有关系了。
4. require
require
加载模块文件: 读入并执行javascript
文件 ,返回该module.exports
对象
(1)简单的加载
Example :
example.js
var sayHi = function (name) {
console.log(name + ' say hi !');
console.log(require.main===module); #false
};
module.exports.sayhi = sayHi;
example-test.js
var say = require('./example.js'); #加载上面的exmple.js
console.log(say.sayhi('labelnet'));
console.log(require.main === module); #true
执行
D:\webworkspace\webpack-demo\commond>node example4-test.js
labelnet say hi !
false
undefined
true
总结:
require.main === module
可以判断模块是直接执行的还是被调用执行的,如果直接执行返回true , 被调用的返回false;
(2)require 加载规则
进行加载时,默认后缀名时 .js , 也就是说 require('./example4.js')
和 require('./example4')
效果实现一样的。
参数格式:
参数格式决定了不同路径寻找模块文件
- “/” 开头 , 绝对路径加载
require('/yuan/dist/example.js')
- “.” 开头 , 相对路径加载,比如 同一目录加载
require('./example4')
require('./example4.js')
- “文件名称”, 加载默认提供的核心模块,package.json 以 配置的模块,当然node_modules以安装的工程
require('jquery')
(3)缓存
每个模块被加载时,只执行一次,其余的都去缓存中获取;
requrie.cache
Example :
require('./example');
require('./example').message = 'hello js';
console.log(require('./example').message);
上面代码,加载了三次example, 第二次添加message 变量,第三次打印message变量;
结果:
D:\webworkspace\webpack-demo\commond>node example5-test.js
hello js
说明 第三次的结果是从缓存中获取的;
删除缓存
删除缓存,必须知道缓存模块的绝对路径,才可以删除;
基本格式 :
delete require.cache[模块绝对路径];
Example :
require('./example');
require('./example').message = 'hello js';
// console.log(module); //可以获取到模块的绝对路径
delete require.cache['D:\\webworkspace\\webpack-demo\\commond\\example.js']; //删除指定模块缓存,缓存是根据绝对路径识别的!!
console.log(require('./example').message);
结果:
D:\webworkspace\webpack-demo\commond>node example5-test.js
undefined
删除全部缓存
Object.keys(require.cache).forEach(function (key) {
delete require.cache[key];
});
5. 加载机制
(1)require 加载机制
对外输出的值,是这个值得拷贝(复制),如果这个值内部值改变,那么对外输出的值并不改变;
Example :
先打印外部值,改变内部值,再次打印外部值;
example.js
var value = 3;
function add() {
value++;
console.log('内部 value +1 : ' + value)
}
module.exports = {
value: value,
add: add,
};
example-test.js
/**
* Created by yuan on 2/21/2017.
*/
var test= require('./exapmle6');
console.log('外部 value 执行1 : '+test.value);
console.log(test.add());
console.log('外部 value 执行2 : '+test.value);
结果:
D:\webworkspace\webpack-demo\commond>node example6-test.js
外部 value 执行1 : 3
内部 value +1 : 4
undefined
外部 value 执行2 : 3
(2)require 内部处理流程 (学习来源)
require
不是一个全局命令,而是指向当前模块的module.require
命令,而后者又调用Node
的内部命令Module._load
。
Module._load = function(request, parent, isMain) {
// 1. 检查 Module._cache,是否缓存之中有指定模块
// 2. 如果缓存之中没有,就创建一个新的Module实例
// 3. 将它保存到缓存
// 4. 使用 module.load() 加载指定的模块文件,
// 读取文件内容之后,使用 module.compile() 执行文件代码
// 5. 如果加载/解析过程报错,就从缓存删除该模块
// 6. 返回该模块的 module.exports
};
上面的第4步,采用 module.compile()
执行指定模块的脚本,逻辑如下。
Module.prototype._compile = function(content, filename) {
// 1. 生成一个require函数,指向module.require
// 2. 加载其他辅助方法到require
// 3. 将文件内容放到一个函数之中,该函数可调用 require
// 4. 执行该函数
};
上面的第1步和第2步,require函数及其辅助方法主要如下。
- require(): 加载外部模块
- require.resolve():将模块名解析到一个绝对路径
- require.main:指向主模块
- require.cache:指向所有缓存的模块
- require.extensions:根据文件的后缀名,调用不同的执行函数
一旦require函数准备完毕,整个所要加载的脚本内容,就被放到一个新的函数之中,这样可以避免污染全局环境。该函数的参数包括require、module、exports,以及其他一些参数。
(function (exports, require, module, __filename, __dirname) {
// YOUR CODE INJECTED HERE!
});
Module._compile
方法是同步执行的,所以Module._load
要等它执行完成,才会向用户返回module.exports
的值 。
转自:https://blog.csdn.net/LABLENET/article/details/56287947
走向Node与Webpack 之路 - CommonJS 模块化的更多相关文章
- Node基础-CommonJS模块化规范
1.在本地项目中基于NPM/YARN安装第三方模块 第一步:在本地项目中创建一个"package.json"的文件 作用:把当前项目所有依赖的第三方模块信息(包含:模块名称以及版本 ...
- webpack前置知识1(模块化开发)
webpack前置知识1(模块化开发) 新建 模板 小书匠 在开始对模块化开发进行讲解之前,我们需要有这么一个认识,即 在没有过多第三方干扰时,成本低收益高的事物更容易获得推广和信赖. 模块化开发就 ...
- ES6 模块化与 CommonJS 模块化
ES6 模块化 import命令用于输入其他模块提供的功能;export命令用于规定模块的对外接口. export 可以有多个,export default 仅有一个 a.js 模块a文件 导出多个方 ...
- webpack学习2.1 模块化开发(JS模块化&CSS模块化)
一.JS模块化 命名空间,COMMONJS,AMD/CMD/UMD,ES6 module 1.什么是命名空间 库名.类别名.方法名 弊端:在命名空间重复生命,要记住完整的路径名(而且很长) var N ...
- vue+node.js+webpack开发微信公众号功能填坑——v -for循环
页面整体框架实现,实现小功能,循环出数据,整体代码是上一篇 vue+node.js+webpack开发微信公众号功能填坑--组件按需引入 修改部门代码 app.vue <yd-flexbox&g ...
- 绝版Node--Sequlize搭建服务(Node全栈之路)
绝版Node--Sequlize搭建服务(Node全栈之路) 参考资料:https://itbilu.com/nodejs/npm/VkYIaRPz-.html 准备环境:Mysql,Node 前沿: ...
- 绝版Node--Sequlize搭建服务(Node全栈之路 二)
在Node全栈之路(一),也就是上篇文章中,我们讲到了sequlize的基本增删该查,这篇文章,我们在上篇文章的基础上继续探讨,讲一下关于sequlize创建的表之间的对应关系 参考资料:https: ...
- Node 使用webpack编写简单的前端应用
编写目的 1. 使用 Node 依赖webpack.jQuery编写简单的前端应用. 操作步骤 (1)新建一个目录 $ mkdir simple-app-demo $ cd simple-app-de ...
- Node.js实战项目学习系列(3) CommonJS 模块化规范
前言 想开始编写Node.js代码,那么我们就必须先熟悉它的模块化规范CommonJS,本文将详细讲解CommonJS规范 本文代码 >>> github 地址 CommonJS N ...
随机推荐
- [转]一步步学习EF Core(2.事务与日志)
本文转自:http://www.cnblogs.com/GuZhenYin/p/6862505.html 上节我们留了一个问题,为什么EF Core中,我们加载班级,数据并不会出来 其实答案很简单,~ ...
- c#基础学习(0719)之异常处理
异常处理的一般代码模式 try { //可能发生异常的代码 //当try中某行代码发生异常后,从该行代码开始,后面的代码都不会继续执行, //程序直接跳转到catch块中进行执行 } catch (E ...
- CSS阴影盒子
box-shadow:inset 横向偏移量 纵向偏移量 模糊范围 扩展范围 阴影颜色: 1.inset :(可选) 内阴影,不设置inset,表示盒子外部显示一个投影.也可写在最后. 2.横 ...
- 页面刷新 location.reload()
* 页面不刷新,但是加了location.reload()后,把炒作失败提示语都刷没了.//成功,不提示,刷新看数据变化ajax success:function(res){ if(res.code= ...
- 基于win32的windows画板程序
功能设计如下: 1.Graphics菜单中可选择图形,支持Rectangle, Circle, Line,选择对应图形,则相应菜单项前面加上选中标志: 2.Options菜单中包含以下选项 a.Col ...
- 14、通过jpa往数据库插数据
这是接着上一篇写的,在上一篇的基础上添加 Controller @RestController public class HelloController { @Resource private Hel ...
- [js高手之路]Node.js实现简易的爬虫-抓取博客所有文章列表信息
抓取目标:就是我自己的博客:http://www.cnblogs.com/ghostwu/ 需要实现的功能: 抓取博客所有的文章标题,超链接,文章摘要,发布时间 需要用到的库: node.js自带的h ...
- CSS流体(自适应)布局下宽度分离原则——张鑫旭
by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=1463 一.简短的前言 ...
- ifconfig命令无法找到,提示bash: ifconfig: command not found
问题就是题目那样,具体解决方法截图如下: 分析问题 1.whereis ifconfig 看一下这个命令在哪个目录下 2.echo $PATH 看一下该目录是否在路经下,注意lunux下是完全区分大小 ...
- web页面超时自动退出方法
思路: 使用 mousemover 事件来监测是否有用户操作页面,写一个定时器间隔特定时间检测是否长时间未操作页面,如果是,退出: 具体时间代码如下(js):var lastTime = new Da ...