day03-node中的模块系统&npm常用命令&Exprtess

301 和 302 状态码区别

  • 301 永久重定向,浏览器会记住
  • 302 临时重定向
node中的模块系统:

在node中便写完应用程序主要是在使用:

1.es语言
  • 浏览器中没有Dom和Bom
2.核心模块
  • http、fs、path、url、net、os、readline、......
  • 核心模块在Node.js自身源码编译时,已经编译成二进制文件
  • 部分核心模块在Node.js进程启动的时候已经默认加载到缓存里面了
3.第三方模块
  • art-template
  • 必须通过npm来下载才能使用
    4.自编写的模块

什么是模块?

  • 每个.js文件就是一个模块
  • 从npm上下载的一个包(可能是由多个文件组成的一个实现特定功能的包)也是一个模块
  • 任何文件或目录只要可以被Node.js通过require()函数加载的都是模块
  • 每个模块就是一个独立的作用域-,模块和模块之间不会互相"污染"
  • 我们可以通过编程的方式,指定某个模块要对外暴露的内容(其实就是指定require的返回值,通过require的返回值对外暴露指定内容)。这个对外暴露内容的过程也叫"导出" `module.exports
CommonJS模块规范:

在node中的JavaScript还有一个重要的概念就是--模块系统。

  • 模块的作用域
  • 使用require方法来加载模块
  • 使用exports接口对象用来导出模块中的成员。

加载和导出的规则
加载requeire:
  var 变量名称 = require(‘模块’);

两个作用:
1.执行被加载模块中的代码
2.得到被加载模块expotts导出接口对象

导出exports:
  • node中是模块作用域,默认文件中的所有成员在当前文件模块有效。

  • 对于希望可以被其他模块访问的成员,我们就需要把这些公开的成员都挂在exports揭露对象中就可以了.
    导出多个成员(必须在对象中):

    exports.a = 123
    exports.b = 'hello'
     exports.c = function (){
        consele.log('ccc')
    }
    exports.d = {
        foo:'bar'
     }
    

导出单个成员(拿到的就是:函数、字符串):

// 如果一个模块需要直接导出某个成员,而非挂载的方式
// 那这个时候必须使用下面这种方式
 module.exports = 'hello'

以下情况会覆盖:

 module.exports = 'hello'
 module.exports = function (x, y) {
   return x + y
}

也可导出多个成员:

 module.exports = {
     add: function () {
      return x + y
 },
  str: 'hello'
}

node中的模块系统原理解析:

demo:
exports和module.exports的引用:
console.log(exports === module.exports) // =>true
exports.foo = 'bar'
  //等价于:
  module.exports.foo = 'bar'

在node.js官网中曾有这样一段注释:

如果你实在分不清楚 exports 和 module.exports
你可以选择忘记 exports
而只使用 module.exports 也没问题
 module.exports.xxx = xxx
 moudle.exports = {}

接下来是一个小案例(有注释)可以区分exports和module.exports的区别:
// {foo: bar}
exports.foo = 'bar'
// {foo: bar, a: 123}
module.exports.a = 123
// exports !== module.exports
 // 最终 return 的是 module.exports
  // 所以无论你 exports 中的成员是什么都没用
  exports = {
      a: 456
  }
 // {foo: 'haha', a: 123}
module.exports.foo = 'haha'
// 没关系,混淆你的
 exports.c = 456
// 重新建立了和 module.exports 之间的引用关系了
exports = module.exports
// 由于在上面建立了引用关系,所以这里是生效的
 // {foo: 'haha', a: 789}
 exports.a = 789
// 前面再牛逼,在这里都全部推翻了,重新赋值
// 最终得到的是 Function
 module.exports = function () {
   console.log('hello')
 }

真正去使用的时候:
导出多个成员:exports.xxx = xxx
导出多个成员也可以:module.exports = {
}
导出单个成员:module.exports


综上所述exports 和 module.exports 的区别总结:

  • 每个模块中都有一个 module 对象
  • module 对象中有一个 exports 对象
  • 我们可以把需要导出的成员都挂载到 module.exports 接口对象中
  • 也就是:moudle.exports.xxx = xxx 的方式
  • 但是每次都 moudle.exports.xxx = xxx 很麻烦,点儿的太多了
  • 所以 Node 为了你方便,同时在每一个模块中都提供了一个成员叫:exports
  • exports === module.exports 结果为 trues
  • 所以对于:moudle.exports.xxx = xxx 的方式 完全可以:expots.xxx = xxx
  • 当一个模块需要导出单个成员的时候,这个时候必须使用:module.exports = xxx 的方式
  • 不要使用 exports = xxx 不管用
  • 因为每个模块最终向外 return 的是 module.exports
  • exports 只是 module.exports 的一个引用
  • 所以即便你为 exports = xx 重新赋值,也不会影响 module.exports
  • 但是有一种赋值方式比较特殊:exports = module.exports 这个用来重新建立引用关系的

requeire方法的加载规则:
  • require优先从缓存加载(demo):
    a.js文件:

    console.log('a.js 被加载了')
    var fn = require('./b')
    console.log(fn)
    

b.js文件:

console.log('b.js 被加载了')
  module.exports = function () {
   console.log('hello bbb')
}

main.js文件:

 require('./a')
 var fn = require('./b')
console.log(fn)

运行结果:


image.png

结论:


image.png

优先从缓存加载
由于 在 a 中已经加载过 b 了

所以这里不会重复加载
可以拿到其中的接口对象,但是不会重复执行里面的代码
这样做的目的是为了避免重复加载,提高模块加载效率


  • require标识符分析:
    1.路径形式模块

./ 当前目录,不可省略
../ 上一级目录,不可省略
/xxx 几乎不用
d:/a/foo.js 几乎不用
首位的 / 在这里表示的是当前文件模块所属磁盘根路径
.js 后缀名可以省略
// require('./foo.js')

2.核心模块:

核心模块的本质也是文件
核心模块文件已经被编译到了二进制文件中了,我们只需要按照名字来加载就可以了
require('fs')
require('http')

3.第三方模块(以art-template为例):

凡是第三方模块都必须通过 npm 来下载
使用的时候就可以通过 require('包名') 的方式来进行加载才可以使用
不可能有任何一个第三方包和核心模块的名字是一样的
既不是核心模块、也不是路径形式的模块
先找到当前文件所处目录中的 node_modules 目录
node_modules/art-template
node_modules/art-template/package.json 文件
node_modules/art-template/package.json 文件中的 main 属性
main 属性中就记录了 art-template 的入口模块
然后加载使用这个第三方包
实际上最终加载的还是文件

如果 package.json 文件不存在或者 main 指定的入口模块是也没有
则 node 会自动找该目录下的 index.js
也就是说 index.js 会作为一个默认备选项

如果以上所有任何一个条件都不成立,则会进入上一级目录中的 node_modules 目录查找
如果上一级还没有,则继续往上上一级查找
。。。
如果直到当前磁盘根目录还找不到,最后报错:
can not find module xxx

  var template = require('art-template')

package.json 包描述文件:
npm:
  • node package manager
    npm的常用命令:
    官网:http://www.npmjs.com
    image.png

    image.png

    image.png

    image.png

    image.png

    image.png
package.json:

具有说明书的性质
这个文件可以通过 npm init - y来初始化出来

  • 建议每个项目的根目录都有一个package.json文件
    建议执行npm install包名的时候加上--save用来保存依赖信息
    ===========================================================

Express:

// 0. 安装
// 1. 引包
var express = require('express')
 // 2. 创建你服务器应用程序
//    也就是原来的 http.createServer
var app = express()
     // 在 Express 中开放资源就是一个 API 的事儿
// 公开指定目录
// 只要这样做了,你就可以直接通过 /public/xx 的方式访问 public 目录中的所有资源了
 app.use('/public/', express.static('./public/'))
 app.use('/static/', express.static('./static/'))
 app.use('/node_modules/', express.static('./node_modules/'))
// 模板引擎,在 Express 也是一个 API 的事儿
// 得到路径
  // 一个一个的判断
 // 以前的代码很丑
       
   app.get('/about', function (req, res) {
  // 在 Express 中可以直接 req.query 来获取查询字符串参数
      console.log(req.query)
    res.send('你好,我是 Express!')
})

app.get('/pinglun', function (req, res) {
  // req.query
   // 在 Express 中使用模板引擎有更好的方式:res.render('文件名, {模板对象})
 // 可以自己尝试去看 art-template 官方文档:如何让 art-template 结合 Express 来使用
 })
// 当服务器收到 get 请求 / 的时候,执行回调处理函数
app.get('/', function (req, res) { 
res.send(`
     <!DOCTYPE html>

<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<h1>hello Express!你好</h1>
</body>
</html>
`)
})

// 相当于 server.listen
app.listen(3000, function () {
 console.log('app is running at port 3000.')
})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,548评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,497评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,990评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,618评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,618评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,246评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,819评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,725评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,268评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,356评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,488评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,181评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,862评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,331评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,445评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,897评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,500评论 2 359

推荐阅读更多精彩内容