简介
简单介绍一下 nodejs 不同的包管理工具,npx 、 npm 、 pnpm 、cnpm 的用法和区别。
一、nodejs包管理工具
npx
npx是Node.js自带的一个命令行工具,主要用于执行包内的脚本或安装并执行一个包。它的主要用途包括:
1. 执行项目中的脚本:可以直接执行node_modules/.bin
目录下的JS文件。例如,npx .bin/some-script
。
2 . 创建项目:用于创建新项目,如npx create-react-app my-app
会创建一个React应用。
3 . 临时使用包:不需要全局安装包,直接使用npx package-name
来执行包中的命令。
4 . 切换Node版本:可以通过npx node@14.15.0
来使用特定版本的Node。
npm
npm是随Node.js一起安装的包管理工具,主要用于安装和管理Node.js项目的依赖。其主要用途包括:
1 . 安装包:通过npm install package-name
来安装包。
2 . 发布包:可以将自己的包发布到npm仓库,供其他人使用。
3 . 管理依赖:在package.json
中声明依赖,通过npm install
来安装这些依赖。
pnpm
pnpm是一个快速的包管理器,主要特点是其安装速度和磁盘空间利用效率。其主要用途包括:
1 . 快速安装:pnpm通过硬链接的方式减少磁盘空间的占用,并且安装速度比npm快。
2 . 硬链接:pnpm在安装包时创建硬链接而不是复制文件,这样可以减少磁盘使用并加快安装速度。
3 . symlinks:通过符号链接管理依赖,进一步优化了安装过程和空间使用。
cnpm
cnpm是淘宝的npm镜像,主要用于加速npm包的下载速度。其主要用途包括:
1 . 替代npm:用法与npm相同,但通过淘宝的镜像服务器下载包,可以显著提高下载速度。
2 . 设置镜像:通过 npm config set registry https://registry.npmmirror.com/
来设置cnpm作为默认镜像。
Yarn
Yarn是由Facebook发起的包管理工具,旨在解决npm在大型项目中的性能问题。Yarn的优点包括:
安装速度快:采用并行安装和缓存机制,显著提升安装速度。
一致性:通过yarn.lock文件确保所有团队成员安装的依赖版本一致,避免版本冲突。
离线安装:支持离线安装,可以在没有网络的情况下使用已缓存的依赖。
总结
npx:主要用于执行脚本或临时使用包,不需要全局安装。
npm:全面的包管理工具,用于安装、发布和管理依赖。
pnpm:快速且节省空间的包管理器,通过硬链接减少磁盘使用并加速安装。
cnpm:淘宝的npm镜像,用于加速包的下载速度。
扩展
在 Node.js 项目中,npm
(Node Package Manager)是用于管理项目依赖的工具。当你使用 npm
安装一个包时,可以通过不同的方式来指定这个包的类型,例如 dependencies
、devDependencies
或 peerDependencies
。这些类型的区别主要在于它们如何影响项目的依赖管理和包的安装方式。
常用安装命令参数
--save
或 -S
这是较老的语法,用于将包添加到项目的 dependencies
中。这意味着这些包是项目运行时必需的,因此它们会被安装到生产环境的 node_modules
目录中。
--save-dev
或 -D
这种语法用于将包添加到项目的 devDependencies
中。这意味着这些包是开发时必需的,比如测试框架、构建工具等,它们不会被安装到生产环境的 node_modules
目录中,而是在开发过程中使用。
示例
npm install --save-dev <package-name>
简写
npm install -D <package-name>
使用 devDependencies
将包标记为 devDependencies
有几个好处:
减少生产环境负载:只有生产必需的包会被安装到生产环境的
node_modules
目录中,这可以减少部署包的大小和安装时间。清晰的依赖管理:开发依赖和生产依赖被明确区分,使得依赖管理更加清晰。
版本控制:在版本控制系统中,你可以更精确地控制哪些依赖是固定的,哪些是灵活的。例如,你可以在项目中锁定生产依赖的具体版本,而允许开发依赖有更多的灵活性。
总结
使用 --save-dev
或 -D
是将包作为开发依赖添加到你的 Node.js 项目中的标准做法。这样做有助于保持你的生产环境干净且高效,同时确保你的开发环境有所有必要的工具和库。
二 、 tauri框架的使用
tauri 安装 可参考 tauri框架 章节
全栈跨平台组件vue、tauri、blazor、maui、flutter对比,rust、py微服务架构可行性分析_maui 多平台python-优快云博客
一.创建新项目
1.创建项目
sudo npx create-tauri-app
或
sudo pnpm create tauri-app
注:sudo 适用于没有root权限的情况
修改文件属组命令:
sudo chown -R xxx:xxx your-project
注: xxx:xxx 修改成自己的属组
修改文件读写权限
sudo chmod -R 755 your-project
键入密码生效
2.选择模版
上图所示表示创建项目成功
3.安装项目依赖
#cd 到项目目录下
cd tauri-app
#使用pnpm 安装项目依赖 为了保证安装速录可以设置仓库源
#pnpm config set registry https://registry.npmmirror.com
pnpm i
4.安装依赖
包管理器安装 Tauri 的 CLI 工具
pnpm add -D @tauri-apps/cli@latest
5.确认url端口
确认前端开发服务器的 URL,一般在上一步操作过程中会显示默认端口。这个 URL 是 Tauri 用来加载您的内容的地址。例如,如果您正在使用 Vite,那么默认的 URL 是 http://localhost:5173。
6.
初始化Tauri项目配置
pnpm tauri init
若存在缓存 可以在命令行后添加 --force
如上图代表初始化成功
使用vscode开发,可以在首次进入提示安装rust的环境:
tauri
rust-analyzer
7.运行项目
pnpm tauri dev
下图表示运行成功
展示界面
8.构建项目
pnpm tauri build
首次编译的时间会比较长,需要在对应的环境下编译需要的应用程序,在window下编程后的文件放在:src-tauri\target\release\bundle 下
msi 安装文件
nsis 安装文件
src-tauri\target\release 下有一个exe的免安装程序
9.项目目录结构
vscode
node_modules
public
src
src-tauri
capabilities #能力(Capabilities)是tauri或插件所提供的,是一组权限
default.json #权限配置文件
gen
schemas #存放描述文件
icons #系统的图标,采用命令生成
src #服务端代码的存放位置
lib.rs #我们安装依赖的配置文件
main.rs #主入口
target #编译后的文件目录
build.rs #build的入口文件
cargo.toml #cargo的配置文件
tauri.conf.json #tauri的配置文件
index.html
package.json
tsconfig.json
vite.config.ts
二 . 旧项目集成
1.安装Tauri 的 CLI 工具
在旧项目根目录 终端命令行 或者 vscode 命令
npm install -D @tauri-apps/cli@latest
2.初始化
步骤同一创建新项目
npx tauri init
3.运行项目
npx tauri dev
注意:按照步骤操作 Cargo.lock:负责追踪依赖的版本
三.rust包管理命令
1.cargo
Rust的包管理和构建工具,用于自动化项目的构建、依赖管理、测试等操作
cargo build
:构建项目。
cargo run
:构建并运行项目。
cargo test
:运行测试。
cargo update
:更新依赖项。
cargo publish
:将包发布到 crates.io(Rust 的官方包仓库)。
2.rustc
Rust编译器,负责将 Rust 代码编译为可执行文件或库
rustc <filename.rs>
:直接编译一个 Rust 源文件,生成可执行文件(默认输出文件名为 a.out
,可以通过 o
选项指定)。
rustc --version
:显示当前安装的 rustc
版本。
3.rustup
Rust的工具链管理器,可以管理不同版本的Rust编译器(rustc)
rustup install <version> :安装指定版本的 Rust。
rustup update :更新已安装的 Rust 工具链。
rustup default <version> :设置默认的 Rust 版本。
rustup override set <version> :为当前目录设置特定的 Rust 版本。
rustup show :显示当前使用的工具链和版本。
rustup component add <toolname> :用来安装一些 Rust 开发中常用的工具
更多详细技术细节和教程可参考文章:
Tauri教程-基础篇-第一节 Tauri项目创建及结构说明_tauri官方文档-优快云博客
<tauri><rust><GUI>基于rust和tauri,在已有的前端框架上手动集成tauri示例-优快云博客
三、vite使用
一、清除缓存
在安装vite插件前 先清理缓存
清除缓存
npm cache clean --force
较新命令
npm cache verify
若 命令一 无效或失败,可使用命令二
更新 npm
npm install -g npm
二、CSS 预处理器
由于 Vite 的目标仅为现代浏览器,因此建议使用原生 CSS 变量和实现 CSSWG 草案的 PostCSS 插件(例如 postcss-nesting)来编写简单的、符合未来标准的 CSS。
话虽如此,但 Vite 也同时提供了对 .scss
,.sass
,.less
,.styl
和 .stylus
文件的内置支持。没有必要为它们安装特定的 Vite 插件,但必须安装相应的预处理器依赖:
# .scss 和 .sass
sudo pnpm add -D sass-embedded # 或 sass
# .less
sudo pnpm add -D less
# .styl 和 .stylus
sudo pnpm add -D stylus
如果使用的是单文件组件,可以通过 <style lang="sass">
(或其他预处理器)自动开启。
Vite 为 Sass 和 Less 改进了 @import
解析,以保证 Vite 别名也能被使用。另外,url()
中的相对路径引用的,与根文件不同目录中的 Sass/Less 文件会自动变基以保证正确性。
由于 Stylus API 限制,@import
别名和 URL 变基不支持 Stylus。
你还可以通过在文件扩展名前加上 .module
来结合使用 CSS modules 和预处理器,例如 style.module.scss
。
文档地址:功能 | Vite 官方中文文档
三、WebAssembly
预编译的 .wasm
文件可以通过 ?init
来导入。 默认导出一个初始化函数,返回值为所导出 WebAssembly.Instance 实例对象的 Promise:
import init from './example.wasm?init'
init().then((instance) => {
instance.exports.test()
})
init
函数还可以将传递给 WebAssembly.instantiate 的导入对象作为其第二个参数:
init({
imports: {
someFunc: () => {
/* ... */
},
},
}).then(() => {
/* ... */
})
在生产构建当中,体积小于 assetInlineLimit
的 .wasm
文件将会被内联为 base64 字符串。否则,它们将被视为 静态资源 ,并按需获取。
注意:
对 WebAssembly 的 ES 模块集成提案 尚未支持。 请使用 vite-plugin-wasm 或其他社区上的插件来处理。
访问 WebAssembly 模块
如果需要访问 Module
对象,例如将它多次实例化,可以使用 显式 URL 引入 来解析资源,然后执行实例化:
import wasmUrl from 'foo.wasm?url'
const main = async () => {
const responsePromise = fetch(wasmUrl)
const { module, instance } =
await WebAssembly.instantiateStreaming(responsePromise)
/* ... */
}
main()
四、内容安全策略(CSP)
由于 Vite 的内部机制,为了部署 CSP 必须设置某些指令或配置。
'nonce-{RANDOM}'
当设置了 html.cspNonce 时,Vite 会为任何 <script>
和 <style>
标签,以及样式表和模块预加载的 <link>
标签添加一个 nonce 属性。此外,当设置了这个选项时,Vite 会注入一个 meta 标签 (<meta property="csp-nonce" nonce="PLACEHOLDER" />
)。
带有 property="csp-nonce"
的 meta 标签的 nonce 值将在开发和构建后的必要时刻被 Vite 使用。
WARNING
确保为每个请求替换的占位符为唯一值。这对于防止绕过资源的策略非常重要,否则很容易被绕过。
data:
默认情况下,Vite 在构建过程中会将小型资源内联为 data URI。允许 data:
用于相关指令(例如 img-src,font-src),或者,通过设置 build.assetsInlineLimit: 0 来禁用它是必要的。
WARNING
不要为 script-src 允许
data:
。这将会允许注入任何脚本。
五、构建优化
下面所罗列的功能会自动应用为构建过程的一部分,除非你想禁用它们,否则没有必要显式配置。
CSS 代码分割
Vite 会自动地将一个异步 chunk 模块中使用到的 CSS 代码抽取出来并为其生成一个单独的文件。这个 CSS 文件将在该异步 chunk 加载完成时自动通过一个 <link>
标签载入,该异步 chunk 会保证只在 CSS 加载完毕后再执行,避免发生 FOUC 。
如果你更倾向于将所有的 CSS 抽取到一个文件中,你可以通过设置 build.cssCodeSplit 为 false
来禁用 CSS 代码分割。
预加载指令生成
Vite 会为入口 chunk 和它们在打包出的 HTML 中的直接引入自动生成 <link rel="modulepreload">
指令。
异步 Chunk 加载优化
在实际项目中,Rollup 通常会生成 “共用” chunk —— 被两个或以上的其他 chunk 共享的 chunk。与动态导入相结合,会很容易出现下面这种场景:
在无优化的情境下,当异步 chunk A
被导入时,浏览器将必须请求和解析 A
,然后它才能弄清楚它也需要共用 chunk C
。这会导致额外的网络往返:
Entry ---> A ---> C
Vite 将使用一个预加载步骤自动重写代码,来分割动态导入调用,以实现当 A
被请求时,C
也将 同时 被请求:
Entry ---> (A + C)
C
也可能有更深的导入,在未优化的场景中,这会导致更多的网络往返。Vite 的优化会跟踪所有的直接导入,无论导入的深度如何,都能够完全消除不必要的往返。
六、支持传统浏览器
若要使用一个插件,需要将它添加到项目的 devDependencies
并在 vite.config.js
配置文件中的 plugins
数组中引入它。例如,要想为传统浏览器提供支持,可以按下面这样使用官方插件 @vitejs/plugin-legacy:
sudo pnpm add -D @vitejs/plugin-legacy
示例 vite.config.js
import legacy from '@vitejs/plugin-legacy'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
legacy({
targets: ['defaults', 'not IE 11'],
}),
],
})
plugins
也可以接受包含多个插件作为单个元素的预设。这对于使用多个插件实现的复杂特性(如框架集成)很有用。该数组将在内部被扁平化。
Falsy 虚值的插件将被忽略,可以用来轻松地启用或停用插件。
七、vite中间件设置开发服务器
在构建 SSR 应用程序时,你可能希望完全控制主服务器,并将 Vite 与生产环境脱钩。因此,建议以中间件模式使用 Vite。下面是一个关于 express (v4) 的例子:
示例 server.js
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import express from 'express'
import { createServer as createViteServer } from 'vite'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
async function createServer() {
const app = express()
// 以中间件模式创建 Vite 应用,并将 appType 配置为 'custom'
// 这将禁用 Vite 自身的 HTML 服务逻辑
// 并让上级服务器接管控制
const vite = await createViteServer({
server: { middlewareMode: true },
appType: 'custom'
})
// 使用 vite 的 Connect 实例作为中间件
// 如果你使用了自己的 express 路由(express.Router()),你应该使用 router.use
// 当服务器重启(例如用户修改了 vite.config.js 后),
// `vite.middlewares` 仍将保持相同的引用
// (带有 Vite 和插件注入的新的内部中间件堆栈)。
// 即使在重新启动后,以下内容仍然有效。
app.use(vite.middlewares)
app.use('*', async (req, res) => {
// 服务 index.html - 下面我们来处理这个问题
})
app.listen(5173)
}
createServer()
这里 vite
是 ViteDevServer 的一个实例。vite.middlewares
是一个 Connect 实例,它可以在任何一个兼容 connect 的 Node.js 框架中被用作一个中间件。
下一步是实现 *
处理程序供给服务端渲染的 HTML:
示例 server.js
app.use('*', async (req, res, next) => {
const url = req.originalUrl
try {
// 1. 读取 index.html
let template = fs.readFileSync(
path.resolve(__dirname, 'index.html'),
'utf-8',
)
// 2. 应用 Vite HTML 转换。这将会注入 Vite HMR 客户端,
// 同时也会从 Vite 插件应用 HTML 转换。
// 例如:@vitejs/plugin-react 中的 global preambles
template = await vite.transformIndexHtml(url, template)
// 3. 加载服务器入口。vite.ssrLoadModule 将自动转换
// 你的 ESM 源码使之可以在 Node.js 中运行!无需打包
// 并提供了一种高效的模块失效机制,类似于模块热替换(HMR)。
const { render } = await vite.ssrLoadModule('/src/entry-server.js')
// 4. 渲染应用的 HTML。这假设 entry-server.js 导出的 `render`
// 函数调用了适当的 SSR 框架 API。
// 例如 ReactDOMServer.renderToString()
const appHtml = await render(url)
// 5. 注入渲染后的应用程序 HTML 到模板中。
const html = template.replace(`<!--ssr-outlet-->`, () => appHtml)
// 6. 返回渲染后的 HTML。
res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
} catch (e) {
// 如果捕获到了一个错误,让 Vite 来修复该堆栈,这样它就可以映射回
// 你的实际源码中。
vite.ssrFixStacktrace(e)
next(e)
}
})
package.json
中的 dev
脚本也应该相应地改变,使用服务器脚本:
示例 package.json
"scripts": {
- "dev": "vite"
+ "dev": "node server"
}
该部分可参考文档:服务端渲染 (SSR) | Vite 官方中文文档
四、vuteify框架
1.安装
pnpm create vuetify
详细安装命令可以参考官方文档
2.项目集成vuetify
在项目中安装vuetify3
npm install vuetify@next
然后安装Vuefity模块依赖
pnpm i -D vuetify vite-plugin-vuetify
pnpm i @mdi/font
配置Vuetify
接下来,你需要配置Vuetify。在项目的src
目录下创建一个plugins
文件夹,并在其中创建一个vuetify.ts
文件。这个文件用于配置Vuetify。
// src/plugins/vuetify.ts
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
export default createVuetify({
components,
directives,
})
主文件中引入Vuetify
修改main.ts
文件,引入并使用Vuetify:
// src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify.ts'
const app = createApp(App)
app.use(vuetify)
app.mount('#app')
添加Vuetify样式
在main.ts
中,确保引入Vuetify的样式:
import 'vuetify/styles' // 引入Vuetify的样式文件
配置CSS处理
// src/plugins/vuetify.js
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import '@mdi/font/css/materialdesignicons.css' // 确保引入Material Design Icons字体图标库的CSS文件(如果需要)
export default createVuetify({
components,
directives,
theme: {
defaultTheme: 'light', // 或者 'dark',根据你的需求设置默认主题
themes: {
light: {
colors: {
primary: '#1867C0', // 主色设置等...
},
},
dark: { /* dark theme settings */ },
},
},
})
配置 Vite 以支持 Vuetify 的样式加载器
由于 Vuetify 使用 Sass,你可能需要配置 Vite 以支持 Sass。这通常可以通过安装并配置 vite-plugin-vuetify
或其他相关的插件来实现。例如,使用 vite-plugin-vuetify
:
npm install vite-plugin-vuetify sass --save-dev
然后在你的 vite.config.ts
或 vite.config.js
中添加配置:
在 vite.config.ts
中配置 Vite 插件:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vuetify from 'vite-plugin-vuetify'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vuetify({ autoImport: true })], // 自动导入组件和指令等配置项可以根据需要调整。
resolve: {
alias: {
'@': path.resolve(__dirname, './src'), // 根据你的项目结构调整别名路径。
},
},
})
Vuetify的Icon组件和mdi包
如果你使用的是Vuetify,并且想直接使用Vuetify的<v-icon>
组件显示MDI图标,你可以通过安装@mdi/js
和@mdi/font
来实现。
安装依赖
方法1
使用npm或yarn安装mdi-vue
npm install mdi-vue
# 或者
yarn add mdi-vue
方法2
npm install @mdi/js @mdi/font
# 或者
yarn add @mdi/js @mdi/font
在项目中引入MDI图标 使用方法对应上面
你可以在组件中直接使用Vuetify的<v-icon>
组件,并通过@mdi/js
包获取图标路径。例如:
方法1
<template>
<v-app>
<v-container>
<mdi-icon icon="account" size="24px" color="blue"></mdi-icon>
</v-container>
</v-app>
</template>
<script>
import { mdiAccount } from 'mdi-vue/icons'
export default {
components: {
'mdi-icon': mdiIcon
},
data: () => ({
icons: [mdiAccount] // 这里可以添加更多的图标
})
}
</script>
方法2
<template>
<v-app>
<v-container>
<v-icon :icon="accountIcon"></v-icon>
</v-container>
</v-app>
</template>
<script>
import { mdiAccount } from '@mdi/js'
export default {
data: () => ({
accountIcon: mdiAccount // 直接使用图标路径作为属性值
})
}
</script>
总结:
比较推荐方法2,因为它充分利用了Vuetify的生态系统,并且与Vue组件系统集成得更好。方法1提供了更多的灵活性,特别是在需要动态加载图标时。
运行
现在,一切设置完毕,你可以启动你的项目:
npm run dev
使用Vuetify组件
在Vue组件中使用Vuetify组件,例如:
<template>
<v-app>
<v-container>
<v-row>
<v-col>
<v-btn color="primary">Click Me</v-btn>
</v-col>
</v-row>
</v-container>
</v-app>
</template>
<template>
<v-app>
<v-container>
<v-row>
<v-col>Hello Vuetify!</v-col>
</v-row>
</v-container>
</v-app>
</template>