大家在每天开始一天新的工作的时候,第一件事就是打开vs code,然后就在命令行输入npm run start,emmm...之后再等待个一小会,项目就跑起来了,就开始愉快的一天了。
那问题来了,你想过npm run xxx之后发生了什么吗?
package.json文件
package.json 用来描述项目及项目所依赖的模块信息,安装包依赖关系都由package.json来管理,开发者几乎不必考虑它们,但是有必要了解package.json中各个字段的含义和使用方法。
例如如下package.json:
{
"name": "doraemon-pocket-task",
"version": "0.0.0",
"scripts": { //重点。。。
"start": "vite",
"build": "tsc && cross-env NODE_OPTIONS=--max_old_space_size=10240 vite build",
"serve": "vite preview",
"test": "jest",
"test:c": "jest --coverage",
"stylelint": " stylelint \"./src\"",
"cspell": "cspell \"src/**/{*.ts,*.tsx,*.js,*.jsx}\"",
"eslint": "eslint -c ./.eslintrc.json \"src/**/{*.ts,*.tsx,*.js,*.jsx}\"",
"checker": "npm-run-all -p eslint cspell stylelint ts-check",
"ts-check": "tsc --noEmit",
"moveAntdcss": "node ./scripts/moveAntdcss.js"
},
"dependencies": {
xxxx
},
"devDependencies": {
//省略很多xxxx
"vite": "^2.8.4"
}
}
- name:项目/模块名称,长度必须小于等于214个字符,不能以"."(点)或者" "(下划线)开头,不能包含大写字母。
- version:项目版本
- author:项目开发者,它的值是你在npmjs.org网站的有效账户名,遵循“账户名<邮件>”的规则,例如:zhangsan zhangsan@163.com。
- description:项目描述,是一个字符串。它可以帮助人们在使用npm search时找到这个包。
- keywords:项目关键字,是一个字符串数组。它可以帮助人们在使用npm search时找到这个包。
- private:是否私有,设置为 true 时,npm 拒绝发布。
- license:软件授权条款,让用户知道他们的使用权利和限制。
- bugs:bug 提交地址。
- contributors:项目贡献者 。
- repository:项目仓库地址。
- homepage:项目包的官网 URL。
- dependencies:生产环境下,项目运行所需依赖。
- devDependencies:开发环境下,项目所需依赖。
- scripts:执行 npm 脚本命令简写,比如 “start”: “react-scripts start”, 执行 npm start 就是运行 “react-scripts start”。
- bin:内部命令对应的可执行文件的路径。而.bin里面的文件可以找到相应的包,就是这里配置的
- main:项目默认执行文件,比如 require(‘webpack’);就会默认加载 lib 目录下的 webpack.js 文件,如果没有设置,则默认加载项目跟目录下的 index.js 文件。
- module:是以 ES Module(也就是 ES6)模块化方式进行加载,因为早期没有 ES6 模块化方案时,都是遵循 CommonJS 规范,而 CommonJS 规范的包是以 main 的方式表示入口文件的,为了区分就新增了 module 方式,但是 ES6 模块化方案效率更高,所以会优先查看是否有 module 字段,没有才使用 main 字段。
- eslintConfig:EsLint 检查文件配置,自动读取验证。
- engines:项目运行的平台/环境。
- browserslist:供浏览器使用的版本列表。
- style:供浏览器使用时,样式文件所在的位置;样式文件打包工具parcelify,通过它知道样式文件的打包位置。
- files:打包是被项目包含的文件名数组;
再package.json中,我们可以看到一个script的属性,当我们执行了npm run start,npm就会在这里寻找到start命令对应的脚本,也就是"vite",换句话说,执行了npm run start就相当于执行了vite,那为什么需要npm脚本属性呢?难道是为了简化我们的命令输入吗?但是我测试发现,当我们直接在终端执行vite时行不通
的,出现了如下的报错
window下:
mac下:
无论是 windows还是mac下都是类似原因导致的无法直接执行,那为什么npm run start,之后却可以运行呢?这主要的原因就在node_modules里面了。
node_modules
在node_modules中,大家通常比较关注modules中的包,但是node_modules中第一个文件夹是.bin,而这个文件夹主要存放命令对应的可执行文件的软链接文件,指向对应第三方依赖的bin文件。
npm 在执行install的时候,会根据第三方依赖中的package.json里面的bin配置,在node_modules下面的.bin目录生成一个可执行文件。生成的可执行文件其实是一个替身文件(软链接文件),这个替身文件真正指向的就是第三方依赖package.json里面的bin配置指向的那个文件。
npm运行script脚本时会自动给脚本路径都加上了node_moudles/.bin前缀,这意味着:你在试图运行script中某个脚本时,实际上是运行node_moudles/.bin下的对应软链接文件。
如果这里找不到相应的软连接,则会尝试去全局的node_modules下面找相应的软连接
友情提示:.vite文件夹存放的是vite的依赖预构建
vite对于在脚本文件中通过import导入
// 裸导入
import * as qs from 'qs';
// 经过 Vite 转换后 import __vite__cjsImport0_qs from "/node_modules/.vite/qs.js?v=f72810ea"; const qs = __vite__cjsImport0_qs;
// 相对路径导入, Vite 暂时没有转换
import { add } from './utils.js';
对于裸导入,Vite 会尝试从node_modules文件夹查询依赖,并重写导入路径。可以看到导入路径被转换为/node_modules/.vite/qs.js?v=f72810ea 。之所以不是/node_modules/qs/xxx,Vite 对node_modules中的依赖进行了预处理,将结果放在了.vite文件夹下。
.bin文件夹
我们展开.bin文件夹中,可以看到
mac下,
文件中start方法指向了一个../dist/node/cli的文件,(下面会看看这个文件)
我们文件夹中发现了vite的符号连接,而这个链接指向是node_modules文件夹下面vite的包
在windows中,是这样的
从图中可以看到,
- 看到文件顶部写着
#!/bin/sh,表示这是一个脚本。 - 文中
../vite/bin/vite.js就只真正执行服务的文件 - 该文件
vite和下面的vite.cmd的含义
-
unix 系默认的可执行文件,必须输入完整文件名 vite
-
windows cmd 中默认的可执行文件,当我们不添加后缀名时,自动根据 pathext 查找文件 vite.cmd
vite文件夹
首先看一下文件的bin文件夹,值得关注的是,在mac中。.bin文件夹中的比特
再看一下目录
大家从图中功能就可以看出,vite主要用了rollup和esbuild,都支持了原生的esm模块,就想他在官网写的
rollup