贡献与魔改指南
贡献与魔改指南
自定义方式应该是有三种:
- 源码修改、贡献
- 修改后贡献
- 修改后发布到自己的npm
- 修改后直接使用
- 替换主题组件
- 主题继承
源码修改、贡献
这里我分了三种源码使用流程:
仅git修改全流程
这一点和其他git项目一致,没啥好说的。
细节上可以参考:https://theme-hope.vuejs.press/zh/contribution.html#%E9%A1%B9%E7%9B%AE%E4%BF%AE%E6%94%B9
# github上pull
git clone https://github.com/LincZero/vuepress-theme-hope.git
cd vuepress-theme-hope
git submodule status # demo和docs,可以不更新。更多项目主题没有用git submodule,属于是monorepe风格的管理
pnpm i
# 修改项目,开发期间可以用 pnpm dev、pnpm docs:vite-build 来调试
git push
# github上pr
打包到自己的新npm的流程
不打包到npm直接使用于项目的流程
别名
这个功能从根本是webpack或vite提供的。
而vuepress和主题也对此有良好支持,例如够支持替换主题里的组件。
主题中可替换的组件:https://theme-hope.vuejs.press/zh/guide/advanced/replace.html#%E5%A6%82%E4%BD%95%E9%80%9A%E8%BF%87%E5%88%AB%E5%90%8D%E6%9B%BF%E6%8D%A2%E7%BB%84%E4%BB%B6
方法
准备好替换组件。这里复制旧组件到新位置,除了需要修改的位置外,还有另一些路径需要改动(如果不是重新造轮子就无需这一步)
// v 这种在components路径下的一般无需修改,@theme-hope对应的tsconfig.json设置的路径映射:"@theme-hope/*": ["./src/client/*.js"] import SidebarChild from "@theme-hope/modules/sidebar/components/SidebarChild"; // v import "../styles/sidebar.scss"; 需要修改成: import "vuepress-theme-hope/sidebar/styles/sidebar.scss"; // v import { resolveSidebarItems } from "./resolveConfig.js"; 需要修改成: import { resolveSidebarItems } from "vuepress-theme-hope/lib/client/modules/sidebar/composables/resolveConfig";
config.ts。Vue别名替换
import { getDirname, path } from "@vuepress/utils" // vuepress别名系统,需要:pnpm install -D @vuepress/utils const __dirname = getDirname(import.meta.url) export default defineUserConfig({ alias: { "@theme-hope/modules/sidebar/components/Sidebar": path.resolve(__dirname, "../../module/sidebar/components/Sidebar.ts"), } })
theme.ts。主题允许可被替换
export default hopeTheme( {...}, {custom: true} )
别名替换的路径问题
这点挺坑的,如果替换的新组件不再import旧组件相对路径的其他东西,那倒不需要担心这个。但如果想复用一些东西,就会非常难受。
下面说一些,仅微改旧组件进行拷贝复用时,路径的修改方法:
复制法
一、复制一份到新路径。不适合递归import这样做,要复制一堆东西,scss倒是可以这样做
node_modules法
二、使用vuepress-theme-hope (编译后,在node_modules) 内的文件。由于是编译过的,会缺失一些文件,但像scss和个别js,可以使用这种方法
另外需要注意,这里的 vueperss-theme-hope/……
的起点是:/node_modules/vuepress-theme-hope/lib/(client/module/)……
(注意1:不能加lib,加了不飘红但编译错,不加飘红但编译对)
(注意2:而且个路径索引还有一定的弹性,有些智能,居然还能让你少写几个路径段)
// 例如:
// v import "../styles/sidebar.scss"; 需要修改成:
import "vuepress-theme-hope/sidebar/styles/sidebar.scss";
// v import { resolveSidebarItems } from "./resolveConfig.js"; // 原写法,错误
// v import { resolveSidebarItems } from "vuepress-theme-hope/lib/client/modules/sidebar/composables/resolveConfig"; // 不飘红但编译错
import { resolveSidebarItems } from "vuepress-theme-hope/sidebar/composables/resolveConfig.js"; // 飘红但编译对
import { resolveSidebarItems } from "vuepress-theme-hope/module/sidebar/composables/resolveConfig.js"; // 这两个都行
// import CommonWrapper from "vuepress-theme-hope/lib/client/components/CommonWrapper" // 不飘红但编译错
import CommonWrapper from "vuepress-theme-hope/components/CommonWrapper.js" // 飘红但编译对
console.log(CommonWrapper.__name);
// v import { ArticleInfoType } from "../../shared/index.js";
import { ArticleInfoType } from "vuepress-theme-hope/client/../shared/index.js"; // 这个就有点神奇了,必须写client再往前退才行
编辑器代码会有飘红
相对路径问题
三、普通相对路径问题
// 如果是相对路径,是基于新组件文件的路径的。但需要特别注意tsc相对路径
tsc路径问题
四、tsc相对路径问题 (tsconfig.json简称tsc)
// @theme-hope对应的tsconfig.json设置的路径映射:"@theme-hope/*": ["./src/client/*.js"]
import SidebarChild from "@theme-hope/modules/sidebar/components/SidebarChild";
// 这里别名替换后案例应该看起来是相对路径,但其实不是
// 这里不类似C的宏,不是简单的字符串替换,而是会将@theme-hop这个符号的位置强行定位到一个固定的位置
// 得益于此,通常将旧组件拷贝为新组件后,这种路径是不需要再去进行修改的
当然不去改动其实是一种取巧而不正规的方法,不改的一个缺点是:编辑器代码会有飘红
想要不飘红,就抄一下tsconfig.ts
import type form 路径
这种情况下,这个import type一般是可选的,用来规范静态类型。如果没空去修改,直接注释掉这行就行了
当然不去改动其实是一种取巧而不正规的方法,不改的一个缺点是:编辑器代码会有飘红
一些原理 (GPT4)
dist与lib目录 (node_modules下)
有的库在node_modules路径下的子路径是dist(例如:@vuepress/utils/dist),而有的则是lib(例如:@vuepress/helper/lib),这两种方式有什么区别吗
dist
和lib
这两个目录通常都是用来存储编译后的代码,但是它们之间的确存在一些差异。
dist
(distribution)目录通常用于存储经过编译和打包后的代码,这些代码可以直接在生产环境中使用。这个目录中的代码通常会被编译为更低版本的JavaScript,以确保在各种环境中的兼容性。另外,这个目录中的文件可能会被压缩和优化,以减少文件大小和提高运行效率。
lib
(library)目录通常用于存储编译后但未打包的代码,这些代码通常是模块化的,可以被其他代码导入使用。这个目录中的代码可能会被编译为更高级的JavaScript,以利用新的语言特性,但通常不会进行压缩和优化。
这两个目录的具体用途可能会根据不同的项目和团队的约定而有所不同,所以如果你在一个项目中看到这两个目录,最好查阅该项目的文档,以了解它们的具体用途。
lib目录的包含问题
// 其中该路径存在:/node_modules/@vuepress/helper/lib/client
import {...} from "@vuepress/helper/client"; // 该写法飘红但编译正确
import {...} from "@vuepress/lib/helper/client"; // 该写法不飘红但运行期会存在错误:[vite] Internal server error: Missing "./lib/client" specifier in "@vuepress/helper" package
这个问题可能是由于你的IDE(例如VS Code)或者其他的类型检查工具(例如TypeScript)对模块路径的解析方式和实际的打包工具(例如Vite,Webpack等)不一致导致的。
在你的例子中,看起来你的IDE或者类型检查工具可能会默认把 @vuepress/helper
解析为 @vuepress/helper/index
或者 @vuepress/helper/main
,然后再从这个文件中导入 client
。但是在实际的打包过程中,Vite可能会直接把 @vuepress/helper/client
解析为 /node_modules/@vuepress/helper/lib/client
。
所以,当你使用 import {...} from "@vuepress/helper/client";
时,虽然IDE或者类型检查工具会提示错误(飘红),但是实际的打包过程中,Vite能够正确地找到对应的文件,所以编译是正确的。
而当你使用 import {...} from "@vuepress/lib/helper/client";
时,IDE或者类型检查工具可能不会提示错误(不飘红),但是在实际的打包过程中,Vite无法找到对应的文件,所以会报错。
为了解决这个问题,你可以尝试以下方法:
- 确认你的IDE或者类型检查工具的配置,确保它们的模块路径解析方式和Vite一致。
- 检查
@vuepress/helper
包的package.json
文件,看看是否有main
或者module
字段指向了错误的入口文件。 - 如果可能,你也可以尝试更新你的IDE、类型检查工具或者打包工具到最新版本,看看是否能解决这个问题。
补充:
@USH2A 群友说的飘红的原因:
类型检查是类型检查,编译是编译,你要怪就怪不是 esm only 吧,cjs 和 esm,再加个 ts,复杂度指数上升,因为根本没有标准做法,只有规范做法,这就导致你抄别人的你自己不能运行的运行,因为每个人的配置不一样