npm init 初始化项目,完成后,会生成一个 package.json 文件,其中包含了项目的元数据和依赖项列表。npm install <package-name> 安装依赖包,默认局部安装,修改生产依赖npm install <package-name> --save(or -S) 局部安装,并修改 package.json 生产npm install <package-name> --save-dev(or -D) 局部安装,修改开发依赖npm install -g <package-name> 全局安装包npm install 根据当前项目已有的 package.json 和 package-lock.json,安装所有依赖。npm uninstall(or rm) <package-name> 卸载包,默认卸载局部安装的,-g 卸载全局安装的npm list(or ls) [<pkg>] 查看已安装的包,会递归显示所有子依赖,--depth=0 只看直接安装的包。--json 输出 jsonnpm update <package-name> 更新包npm run <script-name> 运行 package.json 中定义的脚本。例如,如果 package.json 中有 "scripts": { "start": "node app.js" },则可以运行:npm startnpm install --production 对于服务端项目,安装生产依赖npm install -g <package-name> 安装位置:操作系统的系统目录(例如 macOS/Linux 的 /usr/local/lib/node_modules 或 Windows 的 %AppData%\npm\node_modules),而不是当前项目的 node_modules。安装后,该包的命令行工具(CLI)可以在任何目录下终端直接使用。package.json 无变化。不会记录在当前项目的 package.json 中。npm install <package-name> 是将模块下载到当前命令行所在目录。安装位置:当前项目目录下的 node_modules 文件夹。只有当前项目可以使用。package.json 会记录依赖信息(配合 --save 系列参数)。package.json 文件是项目的配置文件,包含了项目的元数据和依赖项列表。它的基本结构如下:dependencies: 生产依赖。对应 npm install <pkg> --save。项目运行时必须的包(如 vue, react, axios)。用户部署项目时,必须安装这些。devDependencies: 开发依赖。对应 npm install <pkg> --save-dev。仅开发/构建时需要的包(如 vite, webpack, eslint, typescript)。生产环境部署时可以忽略(npm install --production)。peerDependencies: 同伴依赖。常用于开发插件或库。表示你的库依赖宿主环境提供的某个包(例如 Vue 插件依赖 vue),但不自动安装,由用户自己决定版本。optionalDependencies: 可选依赖。安装失败不影响整体流程(常用于特定平台的二进制包)import 了,浏览器或 Node 运行时需要它 → 写在 dependencies。devDependencies。入口文件与模块规范 (Entry & Module Type):它告诉 Node.js 或打包工具,项目的入口在哪里,以及使用哪种模块系统。
"main": "./dist/index.js""module": "./dist/index.mjs""type": "module" 表示项目内的 .js 文件默认被视为 ESM (可以使用 import/export)"type": "commonjs",则 .js 文件默认被视为 CommonJS (使用 require)版本控制 (Semantic Versioning): 它规定了依赖包的版本范围,平衡了“稳定性”和“更新”。防止依赖包自动升级到破坏性更新的大版本(如 Vue 2 升到 Vue 3),导致项目报错。
^1.2.3 (Caret): 允许更新次要版本和补丁版本(1.3.0, 1.2.4),不允许更新大版本(2.0.0)。默认行为。~1.2.3 (Tilde): 只允许更新补丁版本(1.2.4),不允许更新次要版本(1.3.0)。1.2.3: 锁定确切版本。项目元数据 (Metadata) 描述项目的基本信息,主要用于 npm 发布和识别。
name: 包名(发布到 npm 必须唯一)。version: 项目版本(遵循 SemVer 规范)。private: true 表示私有项目,防止意外发布到 npm 公共仓库。engines: 指定需要的 Node.js 版本(如 "node": ">=16")。package-lock.json:锁定确切版本。记录依赖包的确切版本、下载路径、哈希值、依赖树结构。
如果没有 package-lock.json:
lodash@4.17.20。package.json 写的是 ^4.17.0,npm 可能给他安装最新的 4.17.21。4.17.21 有个 Bug,你的项目就挂了。典型配置
{
"name": "my-project", // 项目名
"version": "1.0.0", // 版本
"description": "A sample project", // 项目描述
"main": "index.js", // 主文件路径
"scripts": { // 脚本命令集合
"start": "node index.js",
"test": "mocha test/*.js"
},
"dependencies": { // 生产依赖项
"express": "^4.17.1"
},
"devDependencies": { // 开发依赖项
"mocha": "^9.1.3"
},
"author": "Your Name", // 作者
"license": "ISC" // 许可证类型
}
{
"name": "my-vue-project",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint . --ext .vue,.js,.ts --ignore-path .gitignore"
},
"dependencies": {
"vue": "^3.3.4",
"vue-router": "^4.2.4",
"pinia": "^2.1.6"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.2.3",
"vite": "^4.4.9",
"typescript": "^5.0.2",
"sass": "^1.63.6",
"eslint": "^8.45.0",
"eslint-plugin-vue": "^9.15.1"
},
"engines": {
"node": ">=16.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
npm config set prefix "c:\00nodejs\nodejs\node_global"
npm config set cache " c:\ 00nodejs\nodejs\node_cache"
npm config get prefix //查看npm全局安装保存路径
npm config get cache //查看npm安装缓存cache路径
npm list -global or npm ls -g 列出全局安装的 npm 包及其版本
npm config list -l 查看所有配置
临时指定淘宝镜像源:npm --registry https://registry.npm.taobao.org install express
永久指定淘宝镜像源:npm config set registry https://registry.npm.taobao.org
安装 cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
清空缓存 npm cache clean --force
查看当前的npm镜像设置 npm config get registry
切换新源 npm config set registry 网页链接
包的信息 npm info 包名
__dirname 是 Node.js 提供的一个全局变量,表示当前模块所在的目录的绝对路径。在 Node.js 中,每个 .js 文件都是一个模块,__dirname 变量指向该模块所在的位置。例如,如果 server.js 文件位于 /home/user/project 目录下,那么 __dirname 的值就是 /home/user/project。
path.join() path 模块提供了实用函数来处理文件路径。path.join() 方法用于将一个或多个路径片段组合成一个路径字符串,该字符串将根据当前操作系统使用适当的路径分隔符进行连接。这对于跨平台的路径操作特别有用,因为它会自动处理 Windows 和 Unix 系统之间路径分隔符的不同。
npx appium 当局部安装一个包时,使用 npx 可以在本地运行包中的命令,如果全局安装则可以不需要 npx,不然无法识别命令。
<script src="..."> 和 <link href="..."> 标签。文件太多,网络请求就太多,页面就慢。bundle.js,而是拆分成多个小文件(Chunks)。node_modules 中的依赖单独打包成 vendor.js。 import() 语法手动分割。<script type="module"> 默认是 defer 的(异步加载,不阻塞 HTML 解析)。它天然支持按需加载。// 1. 静态结构
// ✅ ESM 合法
import { foo } from './bar.js';
// ❌ ESM 非法 (SyntaxError)
if (condition) {
import { foo } from './bar.js';
}
// ✅ CommonJS 合法
if (condition) {
const foo = require('./bar');
}
// 2. live Bindings
// counter.js
export let count = 0;
setTimeout(() => { count = 1; }, 1000);
// main.js (ESM)
import { count } from './counter.js';
console.log(count); // 0
setTimeout(() => {
console.log(count); // 1 (因为 count 是引用绑定,值变了这里也能看到)
}, 1500);
背景: 现代浏览器(Chrome/Edge/Firefox)已经原生支持 ESM (<script type="module">)。
做法: 开发环境不打包。生产环境打包
原理:
<script type="module" src="/main.js">。import { foo } from './utils.js'。Vite 的作用:
结果:启动速度取决于文件数量,而不是代码大小。改代码只需替换单个文件缓存,秒级热更新。
生产环境 (Build)
Vite 启动时,会在本地运行一个 Node.js 开发服务器(基于 Koa 或 Express 构建)。浏览器认为它只是在请求一个普通的 HTTP 资源,但实际上这个请求被 Vite 服务器接管了。
[浏览器]
| 1. 请求 <script src="/src/main.ts">
v
[Vite Dev Server (Node.js)] <--- 这里发生“拦截”
| 2. 中间件 (Middleware) 捕获请求
| 3. 识别文件后缀 (.ts)
| 4. 调用 Esbuild/SWC 将 TS 转为 JS
| 5. 返回 Content-Type: application/javascript
v
[浏览器] 接收到的已经是标准 JS 代码,直接执行
import 的路径必须是以下两种之一:./utils.js, ../lib/math.js/src/main.js, https://cdn.example.com/lib.jsimport ... from 'react' 这种裸模块说明符(Bare Specifier)时,它不知道 react 对应哪个 URL。它不会去当前目录找 react.js,更不会去 node_modules 里找。它会直接抛出错误:Failed to resolve module specifier "react"。import ... from 'react' 时,它会执行一套复杂的查找逻辑:node_modules 文件夹找。package.json 的 main 或 exports 字段确定入口文件。Pre-bundling): Vite 启动时,会用 Esbuild 扫描你的代码,把所有 node_modules 里的依赖(如 react)打包成一个或多个标准的 ESM 文件,放在 node_modules/.vite/deps/ 目录下。// 源代码
// src/main.ts
import React from 'react';
import { add } from './utils';
// 浏览器实际收到的 (URL 被重写了)
import React from '/node_modules/.vite/deps/react.js'; // ✅ 变成了浏览器能懂的路径
import { add } from './utils.js'; // ✅ 自动补全了后缀
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' // 支持 .vue 文件
import { resolve } from 'path'
export default defineConfig({
// 1. 基础配置
root: '.', // 项目根目录
base: mode === 'production' ? '/myapp/' : '/', // 开发/生产资源基础路径, 以 / 开头和结尾
mode: 'development', // 模式(可被命令行覆盖)
// 2. 插件
// Vite 本身只处理原生 ES 模块,要支持 .vue、.tsx、PostCSS 等,必须通过插件
plugins: [
vue() // 支持 Vue 单文件组件
],
// 3. 开发服务器配置
server: {
host: '0.0.0.0', // 监听所有地址(局域网可访问)
port: 3000, // 端口
open: true, // 启动时自动打开浏览器
cors: true, // 启用 CORS
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},
// 4. 构建配置
build: {
outDir: 'dist', // 输出目录
assetsDir: 'static', // 静态资源目录
sourcemap: false, // 是否生成 sourcemap
minify: 'terser', // 压缩方式
chunkSizeWarningLimit: 500, // 分块大小警告阈值(KB)
rollupOptions: { // 自定义 Rollup 打包配置(分包、入口等)
input: {
main: 'index.html',
admin: 'admin.html'
},
output: {
manualChunks: {
vendor: ['vue', 'vue-router'],
charts: ['echarts']
}
}
}
},
// 5. 路径别名
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'@components': resolve(__dirname, 'src/components')
}
},
// 6. 环境变量前缀,只有以 VITE_ 开头的环境变量才会被暴露到客户端
envPrefix: 'VITE_'
})
import 本身不是一个对象,而是一个 JavaScript 语言关键字(语法)。但 import.meta 是一个特殊的对象,它是 ES 标准定义的“模块元信息”访问方式。目前,唯一允许的 import.xxx 形式就是 import.meta。标准允许扩展 import.meta,例如:import.meta.resolve()(提案中):动态解析模块路径;import.meta.glob()(Vite 特有):批量导入模块import.meta.env.MODE 的值是由 Vite 在启动时根据你运行的命令自动设置的,它不是写死的,而是由命令行和 mode 配置共同决定。 import.meta.env.* 的引用。它不是一个真正的“变量”,而是一个编译时常量。举个例子:console.log(import.meta.env.MODE)
// Vite 在开发时替换为:
console.log('development')
// 在构建时替换为:
console.log('production')
process 是 Node.js 的全局对象,通常在浏览器中不存在。
loadEnv 是 Vite 提供的工具函数 loadEnv(mode, dir, prefixes)
mode:当前模式(如 'development')dir:项目根目录(通常 process.cwd())prefixes:环境变量前缀(如 'VITE_',空字符串表示不限制)configEnv 的结构:
interface ConfigEnv {
mode: string // 当前模式
command: 'serve' | 'build' // serve=开发,build=生产
isPreview?: boolean // 是否是 vite preview
}
defineConfig 接受两种类型:{ plugins: [...] }(env) => { ... }defineConfig(({ mode, command }) => {return {}}) 就是把 ConfigEnv 对象进行了解构,提取出 mode 和 command 两个属性。如果还需要
isPreview,可以写成 ({ mode, command, isPreview })envPrefix: 'VITE_',只有 VITE_ 开头的环境变量才能被访问(暴露给客户端,即 Vite 将环境变量从 Node.js 环境“传递”到浏览器代码中)const api = import.meta.env.VITE_API_URL 在编译时会被替换为 const api = "https://api.example.com"// main.js(运行在浏览器中)
console.log(import.meta.env.VITE_API_URL) // ✅ 输出: https://api.example.com
console.log(import.meta.env.SECRET_KEY) // ❌ undefined
VITE_ 开头的环境变量常在 vite.config.js 中使用VITE_APP_CONTEXT = /hushiVITE_APP_CONTEXT="/hushi"vite.config.ts 在同一目录npm init vue@latest是一种新型前端构建工具,能够显著提升前端开发体验。它主要由两部分组成:
一个开发服务器,它基于原生ES模块提供了丰富的内建功能,如速度快到惊人的模块热更新(HMR)。
一套构建指令,它使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。
定位: 前端构建工具(更准确说是“开发服务器 + 构建工具”)。
核心创新: 它把“开发”和“生产”分开了。
是前端构建工具,用于将自己写的代码转换成浏览器能够识别的 js 代码,像 Vue 的单文件组件(SFC)浏览器是不能直接运行的,需要 Vite 做转换。
npm install -g create-vite 安装 Vite 的全局 CLI(命令行界面)
create-vite my-vue-app 创建 Vue 项目
npm run dev 启动开发服务器
项目目录结构:
my-vue-app/
├── README.md
├── package.json
├── tsconfig.json
├── vite.config.ts
└── src/
├── assets/
├── components/
├── main.ts
├── App.vue
└── index.html
src 目录包含源代码文件。main.ts 是应用程序的入口文件。App.vue 是根组件。vite.config.ts 是 Vite 的配置文件。npm exec(以前叫 npx)。npm init <pkg>:npm init 只用来初始化 package.json。后来为了方便,npm 增加了特性:如果后面跟了包名,它会自动去运行 create-<pkg> 这个包。npm exec create-<pkg>。npm init vue@latest 实际上是在运行 create-vue 这个包。npm create <pkg>:create 命令。npm exec create-<pkg>。npm create vite@latest 实际上是在运行 create-vite 这个包。npm init vue 和 npm create vue 效果完全一样。但社区趋势是逐渐统一使用 npm create,因为语义更准确。npx 是 npm exec 别名。负责下载并临时运行任意 npm 包。[开发者终端]
│
├── 敲命令 (如 `vite`)
│ │
│ ├── 1. 查系统 PATH (全局安装目录) ✅ 优先
│ └── 2. 找不到? → 提示 npx 临时运行
│
└── 跑脚本 (如 `npm run dev`)
│
├── 1. 查 ./node_modules/.bin (局部安装) ✅ 优先 (项目隔离)
└── 2. 找不到? → 查系统 PATH (全局安装) ⚠️ 不推荐依赖
[npx 命令]
│
└── 查 ~/.npm/_npx (缓存目录) → 下载 → 运行
(不在 PATH 中,只能主动调用)
