node运行js文件
在命令行输入node 文件名 node index.js
后会运行对应的文件
在运行时还可以传递参数: node index.js test=test a=a
let test=1;
let a=2;
console.log(test,a); //
这样直接获取是获取不到的,因为参数是放在process内置对象上的
这些传递的参数都是放在process内置对象上的,proces上面有很多属性,参数放在argv上:
可以通过process.argv来获取传递的参数(在package.json中配置的脚本中传递的参数就是用的process.argv)
const test = 1;
const a = 2;
console.log(test, a);
console.log(process.argv)
node中常见的对象
process提供node进程的相关对象
console:用来调试控制台的
定时器:
setTimeout
setInterval
setImmediate(callback())
process.nextTick(callback())
_ _ dirname
:当前文件所在的目录结构,只返回到当前文件所在的上一级目录
_ _filename
:目录+文件的位置
global和 window
在window中全局对象都在window上,在node中全局对象都在global上
globalThis == global
模块化
如果没有模块化会存在很多问题例如:使用var定义的变量作用域的问题。
目前使用比较多的模块化是es模块化和commonJs模块化
commonJs模块化
commonJs主要用于node环境中,webpack具备 commonJs的转换和支持功能。
在node中每一个js文件都是一个单独的模块,使用eports和module.exports对模块的内容进行导出,使用require函数导入其他模块(自定义模块、系统模块、第三方模块)的内容。
eports导出
const a =1
const b =2
exports.a =a
exports.b=b
const bar =require("./index.js")
console.log(bar.a)
console.log(bar.b)
bar变量相当于exports变量,这样做会存在问题:
因为exports是个对象,而bar等于exports,当bar改变时exports也会改变。即在文件中可以修改模块中的变量。但是模块中的变量应该是私有外,只能由它自己改变,而不能由外部改变,所以在开发中exports使用较少。
module.exports
commonJs中是没有module.exports的概念的,但是为了实现模块的导出node中使用了一个Module类,每一个模块都是Module的一个实例,也就是一个module。
module中有一个属性exports,导出的变量存放在它身上,所以module.exports =exports =上面的bar。
另外module的exports属性是对exports对象的一个引用,exports能做到的它也能做到,但是它还有exports没有的优点。所以Node中使用module.exports导出的,而不是用exports导出的。.
通过require导入的实际上是module.exports,所以bar应该指向module.exports,而module.exports与exports指向同一个地址,所以module.exports=exports=bar,这样修改bar还是会修改导出的对象。但是module.exports={}却不一样。
module.exports.a=a
module.exports.b=b
const bar =require('./test.js')
但是当 module.exports等于一个新对象时,就不在指向模块中的对象和内存地址,而是指向一个新的内存地址,而bar指向 module.exports,当bar改变时只会影响新的对象,不会影响原对象。
module.exports={
a,
b
}
const bar =require("./test")
一般使用 module.exports={}导出,使用require导入。
require导入的细节
require是一个函数,它可以帮助我们导入一个模块,require也是有查找规则的:
1.导入的是一个Node核心模块时比如path,http,会直接返回核心模块并停止查找
const path =require('path')
2. 以./ …/或/开头的:
第一步:
**首先会把它当成一个文件夹在对应的目录中开始查找,**如果有后缀名,会按照后缀名的格式查找比如 require(“./index.js”)会查找js文件。
如果没有后缀名,会按照下面的顺序查找:
直接查找文件xx
查找xx.js
查找 xx.json
查找 xx.node文件
第二步:
没有找到对应的文件,会将它作为一个目录 在目录下查找文件哎,查找顺序:
查找xx.js
查找 xx.json
查找 xx.node文件
如果这样还没找到就会报错 not found
- 直接写文件名比如axios这样:
他会现在当前文件夹中查找node_modules,在node_modules下查找对应文件夹下的index.js文件
如果没有找到还会到同一目录下的其他文件夹下查找,没找到就会报错 not found
commonJs是同步加载的,在服务器端没有问题,但是在浏览器端,会阻塞后续代码的加载,所以在浏览器端不使用commonJs,早期使用AMD和CMD,es模块化出现后就不在使用AMD和CMD。
es模块化
export导出和import导入
export导出
//test.js
const a = 1
cosnt b =2
export {
a,
b
}
import导入
//index.js
//这里的文件后缀不能省略
import {a,b} from "./test.js"
在html中使用:
//
<script src="./index.js" type="module"></script>
使用模块化后要开启本地服务,不能直接打开文件,通过Open with Live Server打开
export在导出时改名
//导出
export {
a as aa
}
//导入
import { aa } from "./xxx.js"
export 还可以导出单个变量
export const aa = "1"
export function sty() {
}
import在导入时也可以改名
import { a as aa } from "./xxx.js"
import * from “xxx.js” 将一个模块中所有导出(export)的内容导入到当前模块中。
export 和import 结合使用
export from 可以从一个文件中导出变量
在开发或者封装功能库时可以统一接口规范
export {test} from "./xxxx.js"
export {test as t} from "./xxxx.js"
export * from "./xxxx.js"
default
默认导出,一个模块中只能有一个默认导出,在导入时可以不用{},导入时还可以自己指定名字。
export default function(){
}
import test from "./sss.js"
import函数
如果想要根据某个条件导入模块直接使用import 导入会报错,使用Import 导入只能在模块的顶层使用.
因为 ES Module 在被js引擎解析时就必须知道它的依赖关系,这个时候js代码没有任何运行,所以无法在进行类似于if这样的语句中判断代码是否执行。
let first = true
if(first){
first = false
import {test} from "./xxx.js"
}
可以使用import函数导入,import("./xx.js")
它本身是一个promise:
import("./xx.js").then((res)=>{
console.log(res)
})
import 还有一个meta属性,import.meta它包含了这个模块的信息,但是有兼容性问题,它是在es11(es2020)中提出的。
包管理工具
npm
Node Package Manager 是node包管理器,安装node是会自动安装它。
npm 的一些命令
初始化一个新的Node.js项目 npm init
运行npm init命令将会生成一个package.json
全局安装 npm install xx -g 和 项目(局部)安装 npm install xx 全局安装后 可以在任意地方使用
安装到开发依赖 npm install xxx -D或 npm install xxx --save-dev
卸载依赖包 npm uninstall xxx
npm uninstal xxx -D
npm uninstal xxx --save-dev
强制build npm rebuild
package.json
package.json部分属性
package.json常见的属性
部分属性说明
main属性设置程序的入口
使用 const axios = require(“axios”)导入模块时没有写明后缀名会按照一定的规则匹配。
但是设置mian属性后就会按照mian属性查找文件,直接查找axios下的index.js
scripts属性用于配置一些脚本命令,它以键值对的形式存在:
在这里运行脚本实际上就是npm run xxx
有些命令也可以通过npm xxx,不带run,事实上它们是等价的,对于start,test,stop,restart可以忽略run直接用npm xxx
dependencies 在生产环境中开发环境中都会用到的包如vue,vue-router,react,axios,redux等,在打包时会打包到文件中。
devDependencies 指定生产环境中不需要的一些包,只有在生产环境中才会用到的文件如webpack,babel等
可以通过 npm install xxx -D或 npm install xxx --save-dev
把它安装到devDependencies中,在打包时不会打包到文件中
peerDependencies 有一些项目依赖关系是对等的也就是一个包是以另一个宿主包为前提的。如element-plus是依赖于vue3的 aut design 是依赖于 react的。
engines: 用于指定node和npm的版本号,在安装过程中会先检查版本如果版本不符合就会报错。
"engines": {
"node": ">=8.9",
"npm": ">= 3.0.0"
},
browserslist 用于配置打包后的js的浏览器兼容情况,
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
版本号的详细说明
除了version项目的版本号外,安装的依赖包也有版本号如:
以 “@ant-design/icons”: “^5.3.1”,版本主要有三部分组成 主版本号X,次版本Y号,修订号Z。
主版本号:表示一个库的大版本不同,它会提供一些新的功能比如vue2( “vue”: “2.6.10”,)和vue3(“^3.3.4”)
次版本号:它在提供新功能的前提下还会兼容之前的版本。
修订号:会修复一些兼容性问题或bug.
^
和~
的区别:
x.y.x:表示一个明确的版本号。
^x.y.z:表示x的版本保持不变,y,z永远都是最新的。
~x.y.z:表示x,y不变,z永远都是最新的。
package-lock.json
package-lock.json的属性:
在npm5后,npm支持缓存策略。缓存原理:
package-lock.json的作用:
1.确保依赖版本一致性,文件会记录当前项目依赖包的确切版本号。可以确保在不同开发环境中安装依赖时,都会使用相同的版本,避免因为版本不一致导致的问题。
2.快速安装依赖,项目中存在package-lock.json文件时,npm会优先根据该文件中的信息来安装依赖
3.锁定依赖树结构,package-lock.json文件中记录了依赖包之间的依赖关系,以及安装时的顺序。这样可以确保在不同时间和环境下,项目的依赖树结构是一致的,避免因为依赖树结构不同而导致的问题。
其他的包管理器 yarn ,cnpm ,npx,pnpm,
yarn:在早期npm 存在许多问题,为了弥补npm的缺陷yarn出现了。
cnpm:由于npm仓库在国外,所以安装包的速度慢,因此需要切换镜像:
查看npm镜像 npm config get registry
设置淘宝镜像:npm config set registry https://registry.npmmirror.com
切换会npm镜像:npm config set registry https://registry.npmjs.org
在切换的过程中可能会出现问题,所以出现了cnpm,它解决了在中国访问npm官方源速度慢的问题。通过使用cnpm,可以加快包的下载速度,提高开发效率。
npx是npm 5.2.0版本引入的一个工具,它的作用是临时安装并执行一个Node.js包,而无需将其永久安装到全局环境中。通过npx,可以直接运行项目中安装的命令行工具,而无需手动设置环境变量或全局安装这些工具。
其他作用:
执行局部命令时(以webpack为例)有两种方式:
1.直接在node_module下的webpack文件中执行命令( node ./node_module/.bin/webpack --version)
2. 在scripts定义脚本
“webpack”:“webpack --version”
有了npx后 可以直接使用 npx webpack --version
,它会自动到当前目录的node_module/.bin下查找对应命令
pnpm是一个替代npm和yarn的包管理工具,它的主要特点是采用符号链接的方式来共享包,而不是像npm和yarn那样将包复制到每个项目中。这种方式可以节省磁盘空间,并且可以加快安装和更新包的速度。pnpm还支持并发安装,可以更好地利用网络带宽,提高包的安装效率。
pnpm
硬链接和软链接
硬链接:电脑中多个文件共享同一个共享单元,删除一个文件后其他文件还可以继续访问。
软链接:包含一条以绝对或相对路径指向其他文件或目录,删除这个文件后就不能访问到电脑中存储的数据了。修改硬链接会影响到原数据。
创建硬链接 :mklink /H hard_link source_file
(Windows系统)
创建软链接:mklink soft_link source_file
(Windows系统)
pnpm的作用
当npm或yarn有100个项目时,所有的项目都有同一个依赖包,那么硬盘上就会保存100个依赖包的副本。
而pnpm依赖的所有的包都会放到一个统一的位置。
对于同一个依赖包的相同版本,磁盘上只有这个依赖包的一份文件。
同一依赖包的不同版本,仅有不同版本之间的不同文件会被保存起来。
当安装包时,它所有的文件都会硬链接到一个位置,不会额外占用空间。
pnpm的非扁平的node_module目录
通过npm或yarn安装的依赖包都会放到node_module的根目录下。如果你没有安装某个依赖时,会报错,但是如果其他的包有这个依赖,所有的包都在node_module的根目录下,就会在其他包中找到这个依赖。
而pnpm 在node_module下还有一个.pnpm文件,安装的所有依赖实际上是放在.pnpm下的,node_module的其他文件通过软链接可以访问到.pnpm下与他对应的文件,不会访问到其他文件