Node.js 简介、模块化机制和包管理机制
# Node.js 简介
Node.js 是一个基于 Google V8 引擎的、跨平台的 JavaScript 运行环境,主要运行在服务器端,能够以 JS 的方式编写服务端程序,与传统浏览器中运行的 JS 不同,Node.js 底层采用 C++,可以读取文件、使用多进程、启动 HTTP 服务等。
# Node.js 的版本管理
由于开发过程中可能的版本切换需求(比如:新特性的兼容问题等),需要一个 Node.js 的版本管理工具。
以下是可供的选择:
n
: 一个 npm 全局的开源包,是依赖 npm 来全局安装、使用的fnm
: 快速简单,兼容性支持 .node-version 和 .nvmrc 文件nvm
: 独立的软件包,Node Version Manager
在实际开发中,nvm 用的会多一些。
# Node.js 特点
- 异步 IO:当 Node.js 执行 I/O 操作时,会在响应返回并恢复操作,而不是阻塞线程并浪费 CPU 循环等待
- 单线程:保持了 JavaScript 在浏览器中单线程的特点
优点在于不会发生死锁、没有线程上下文切换带来的开销
缺点在于无法利用多核 CPU、健壮性不足等(可以解决) - 跨平台:兼容 Windows、MacOS、Linux/Unix 操作系统,主要得益于 Node.js 的标准库建立在底层的封装之上
# 模块化机制
与 Java 类似,在开发团队开发过程中,有可能有两个 JS 脚本声明了相同的变量名或函数名,此时运行在同一个网页中就会出现变量污染、副作用等问题,导致代码逻辑无法正常运行,于是引入了模块化机制,方便 import/export
# CommonJS 规范
注意:CommonJS 规范只是一种规范,需要具体的实现才能正常运作(比如依靠 Node.js)
CommonJS 的导入导出语法如下:
// 导出定义的函数 | |
const hello = () => console.log('Hello World!'); | |
exports.hello = hello; | |
// 或者用 | |
// module.exports = { myHello: hello } | |
// 也可以 | |
// 注:exports 其实就是 module.exports,都是 JS 对象 |
// 导入定义的函数 | |
const { hello } = require('./greeting.js') | |
// 或者用 | |
// const { myHello: hello } = require('./greeting.js') | |
// 注:其实就是 JS 解构语法,require 只是一个函数 | |
// 下面就可以正常使用了 | |
hello(); |
# CommonJS 的缓存机制
由于在浏览器中运行时是联网加载,如果每次 require 都需要重新遍历查找,性能会比较差,而且有时候模块中的代码有副作用,所以 require.cache 中缓存了加载过的模块。
如果要每一次重新加载,可以参考以下代码:
// 有缓存 | |
const mod1 = require('./foo'); | |
const mod2 = require('./foo'); | |
console.log(mod1 == mod2);// true | |
// 无缓存 | |
function requireUncached(module){ | |
delete require.cache[require resolve(module)]; | |
return require(module); | |
} | |
const mod3 = requireUncached('/foo') | |
console.log( mod1 === mod3); // false |
# ES Modules(ESM)
ES Modules 是 ES6 原生支持的一个模块化机制,其导入导出语法如下:
// 导出 | |
export default 1 | |
export const name ='lxfriday' | |
export { age } | |
export {name as nickname} | |
export { foo } from './foo-bar' | |
export * from './foo-bar' | |
// 导入 | |
import React from 'react' | |
import * as react from 'react' | |
import { Component } from 'react' | |
import {default as a} from 'react' | |
import {Button as Btn} from 'antd' | |
import 'index.less' |
# CommonJS 对比 ESM
- CommonJS 模块输出的是一个值的拷贝;ESM 模块输出的是值的引用
- CommonJS 模块是运行时加载;ESM 模块是编译时输出 (提前加载)
注:可以混用,但是不建议 (import commonjs 或者 import 中 require)
# 包管理机制
Node.js 中有一个包管理器: npm
,提供了安装、删除等其它命令来管理包。
常用的命令有:
- npm init
- npm config
- npm run [cmd]
- npm install [pkg]
- npm uninstall [pkg]
- npm update [pkg]
- npm info [pkg]
- npm publish
用 npm 进行包管理的目录下一般都有 index.js
和 package.json
这两个文件。
在 package.json 中,有以下属性需要注意:
- name 包名称
- version 版本号
- main 入口文件
- scripts 执行脚本
- dependencies 线上依赖
- devDependencies 开发依赖
- repository 代码托管地址
更多 package.json 配置详见 npm Docs
参考:
字节青训营课程