Skip to content

Commit

Permalink
style: format docs (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
stout-ni authored Aug 15, 2024
1 parent 2798a41 commit 0079ff6
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 23 deletions.
18 changes: 9 additions & 9 deletions _posts/2023-12-26-stencil-code-0.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,29 @@ Stencil 是 Ionic 团队开源的库,以上是摘自 Stencil 官网的介绍

## 项目概览

```shell
```sh
git clone https://github.com/ionic-team/stencil
```

一般来说从零开始上手一个仓库源码,通常我们最重要的第一件事就是看这个项目的入口。打开`package.json`文件,除了 npm 包名、版本等基本信息外,通过 main、module、types 我们可以得知项目的主入口在`src/internal/stencil-core`,里面分别导出了 CommonJS 模块、ES 模块和 TypeScript 类型声明,用于在不同的模块系统和开发环境中正确加载和使用包。
一般来说从零开始上手一个仓库源码,通常我们最重要的第一件事就是看这个项目的入口。打开 `package.json` 文件,除了 npm 包名、版本等基本信息外,通过 main、module、types 我们可以得知项目的主入口在 `src/internal/stencil-core`,里面分别导出了 CommonJS 模块、ES 模块和 TypeScript 类型声明,用于在不同的模块系统和开发环境中正确加载和使用包。

但是通过`src/internal/stencil-core/index.d.ts`可以看到所有导出的接口都应该在`internal`目录下,但是在仓库中却找不到这个目录。其实稍一猜就能猜到这是打包之后产物的目录,只是在`.gitignore`中隐藏了。之所以顺便讲一讲 Stencil.js 的打包和编译流程,是因为这个项目乍一看整个仓库只有一个`package.json`,但其实是一个 Monorepo,只不过区别在于相比普通的 Monorepo,它并非是按照一个 workspace 就是一个 npm 包的样子进行分包。因此要想了解具体代码的分布还是需要看一下它的打包规则才知道核心代码具体放在哪里。
但是通过 `src/internal/stencil-core/index.d.ts` 可以看到所有导出的接口都应该在 `internal` 目录下,但是在仓库中却找不到这个目录。其实稍一猜就能猜到这是打包之后产物的目录,只是在 `.gitignore` 中隐藏了。之所以顺便讲一讲 Stencil.js 的打包和编译流程,是因为这个项目乍一看整个仓库只有一个 `package.json`,但其实是一个 Monorepo,只不过区别在于相比普通的 Monorepo,它并非是按照一个 workspace 就是一个 npm 包的样子进行分包。因此要想了解具体代码的分布还是需要看一下它的打包规则才知道核心代码具体放在哪里。

## 项目编译

我们还是了解一下 Stencil 整个项目的编译流程,查看了`package.json`的 build scripts 之后可以看到 Stencil 的项目编译方式:先通过 tsc 编译 TypeScript 类型声明,通过 Rollup 编译 CommonJS 模块和 ES 模块,编译脚本主入口是`scripts/build/build.js``createBuild`方法。整体的打包和编译流程主要如下:
我们还是了解一下 Stencil 整个项目的编译流程,查看了 `package.json` 的 build scripts 之后可以看到 Stencil 的项目编译方式:先通过 tsc 编译 TypeScript 类型声明,通过 Rollup 编译 CommonJS 模块和 ES 模块,编译脚本主入口是 `scripts/build/build.js``createBuild` 方法。整体的打包和编译流程主要如下:

1. 清空所有打包目标路径文件夹
2. 打包`src/sys/node/bundles`下的文件(主要是导出一些 Node.js 包),如果没有缓存则通过 Webpack 打包并写入缓存
3. 接着按 npm 包的维度进行打包,最后返回一个 `RollupOptions`数组
2. 打包 `src/sys/node/bundles` 下的文件(主要是导出一些 Node.js 包),如果没有缓存则通过 Webpack 打包并写入缓存
3. 接着按 npm 包的维度进行打包,最后返回一个 `RollupOptions` 数组

`scrips`目录下还可以看到有一个`scripts/esbuild`目录,因此 Stencil 的代码仓库里其实包含了 Rollup、Webpack 和 Esbuild 三种打包工具。但看了一下代码,最主要的 internal 包还没有接入 Esbuild,因此我的猜测是 Stencil 会准备将 Webpack 编译的部分全部迁移到 Esbuild 上,抑或是两者并存的形式。
`scrips` 目录下还可以看到有一个 `scripts/esbuild` 目录,因此 Stencil 的代码仓库里其实包含了 Rollup、Webpack 和 Esbuild 三种打包工具。但看了一下代码,最主要的 internal 包还没有接入 Esbuild,因此我的猜测是 Stencil 会准备将 Webpack 编译的部分全部迁移到 Esbuild 上,抑或是两者并存的形式。

## 项目结构

下面可以大致看一下`src`下的源码结构,并讲解一下部分目录的主要用途。
下面可以大致看一下 `src` 下的源码结构,并讲解一下部分目录的主要用途。

```shell
```sh
├── app-data
├── app-globals
├── cli
Expand Down
21 changes: 10 additions & 11 deletions _posts/2024-01-19-expo-router-v3-monoerpo.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ categories: Expo ReactNative

> 示例代码参考:[expo-router-monorepo-example](https://github.com/stout-ni/expo-router-monorepo-example)
参考[官网文档](https://docs.expo.dev/guides/monorepos/#create-our-first-app)一直操作到添加完`metro.config.js`文件。
参考[官网文档](https://docs.expo.dev/guides/monorepos/#create-our-first-app)一直操作到添加完 `metro.config.js` 文件。

接着如下添加`index.js`文件:
接着如下添加 `index.js` 文件:

```js
import "expo-router/entry";
Expand All @@ -25,27 +25,26 @@ import "expo-router/entry";

## 排查思路

首先看一开始页面上的报错毫无头绪,到具体的 node_modules 找`@expo/cli`这个包也看不到`package.json`里导出了 src 这个源文件目录。
首先看一开始页面上的报错毫无头绪,到具体的 node_modules 找 `@expo/cli` 这个包也看不到 `package.json` 里导出了 src 这个源文件目录。

````plain
```plain
TypeError: ExpoResponse is not a constructor
at getHtml (node_modules/@expo/cli/src/start/server/metro/createServerRouteMiddleware.ts:107:20)
at runNextTicks (node:internal/process/task_queues:60:5)
at processTimers (node:internal/timers:511:9)
at handler (node_modules/@expo/server/src/index.ts:149:26)
at node_modules/@expo/server/src/vendor/http.ts:36:24
```
````
```

其实页面上的报错只是一个障眼法,具体的错误可以在命令行里看到:

> Metro error: Unable to resolve module ./node_modules/expo-router/entry from apps/mobile/.:
结合稍微看两眼文档就知道这是由于 Expo 默认不兼容 Monorepo 引起的路径问题。但如果沿着 Expo 的官方文档一步步走下去,到了添加`index.js`这一步就有问题了,因为官方文档使用的不是 Expo Router 版本的项目,没有`App.[jt]sx`文件,只有一个`app`目录。
稍微看两眼文档就知道这是由于 Expo 默认不兼容 Monorepo 引起的路径问题。但如果沿着 Expo 的官方文档一步步走下去,到了添加 `index.js` 这一步就有问题了,因为官方文档使用的不是 Expo Router 版本的项目,没有 `App.[jt]sx` 文件,只有一个 `app` 目录。

因为很明显可以知道`registerRootComponent`是一个用于指定根组件的函数,因此这个时候的思路就在于,怎么去找到 Expo Router 里的入口文件,也就是此时该从哪里去 import 这个目前不存在的 App。
因为很明显可以知道 `registerRootComponent` 是一个用于指定根组件的函数,因此这个时候的思路就在于,怎么去找到 Expo Router 里的入口文件,也就是此时该从哪里去 import 这个目前不存在的 App。

然后我们就可以去看一看官网让我们替换`package.json`中原来的 main 入口,也就是`expo-router/entry`这个东西。直接去 node_modules 里就能找到这个文件。
然后我们就可以去看一看官网让我们替换 `package.json` 中原来的 main 入口,也就是 `expo-router/entry` 这个东西。直接去 node_modules 里就能找到这个文件。

```js
// `@expo/metro-runtime` MUST be the first import to ensure Fast Refresh works
Expand All @@ -60,6 +59,6 @@ import { renderRootComponent } from "expo-router/build/renderRootComponent";
renderRootComponent(App);
```

可以看到这里的逻辑只有一个,就是调用`renderRootComponent`这个方法,它的参数同样是一个 App 入口。那么问题就真相大白了:对于非 Monorepo 的情况来说,入口文件路径是固定的,也就是这里引入的 App。但是在 Monorepo 里,由于依赖都安装在一个 node_modules 中,项目的 node_modules 中找不到这个入口,于是就只能我们通过手动添加一个入口的方式去注册这个根组件。
可以看到这里的逻辑只有一个,就是调用 `renderRootComponent` 这个方法,它的参数同样是一个 App 入口。那么问题就真相大白了:对于非 Monorepo 的情况来说,入口文件路径是固定的,也就是这里引入的 App。但是在 Monorepo 里,由于依赖都安装在一个 node_modules 中,项目的 node_modules 中找不到这个入口,于是就只能我们通过手动添加一个入口的方式去注册这个根组件。

那么最简单的解决方式就是直接在`index.js`里手动引入一下这个`expo-router/entry`,让所有的路径解析都让 Monorepo 的包管理工具(yarn 或者 pnpm)去解决,我们则不需要关心。
那么最简单的解决方式就是直接在 `index.js` 里手动引入一下这个 `expo-router/entry`,让所有的路径解析都让 Monorepo 的包管理工具(yarn 或者 pnpm)去解决,我们则不需要关心。
6 changes: 3 additions & 3 deletions _posts/2024-06-29-us-visa.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ categories: 杂谈
<details>
<summary>小小的吐槽一下</summary>

> 该网站的难用程度超过我见过的所有政府网站,说是到了反人类的级别我觉得也不为过。这个用 ASP.NET 开发的网站看起来就像是一个大学生的 .NET 程序设计结课作业,每一次的表单刷新都在考验着我的忍耐极限。
>
> 但是能在如今的互联网时代还保持这样没有使用任何复杂的现代前端技术,如丁真一般纯粹的网站,何尝不是一种程序员通过逆工业化对抗现代前端发展的反叛精神呢?
该网站的难用程度超过我见过的所有政府网站,说是到了反人类的级别我觉得也不为过。这个用 ASP.NET 开发的网站看起来就像是一个大学生的 .NET 程序设计结课作业,每一次的表单刷新都在考验着我的忍耐极限。

但是能在如今的互联网时代还保持这样没有使用任何复杂的现代前端技术,如丁真一般纯粹的网站,何尝不是一种程序员通过逆工业化对抗现代前端发展的反叛精神呢?

</details>

Expand Down

0 comments on commit 0079ff6

Please sign in to comment.