Skip to content

Commit

Permalink
chore: phrasing (10-minimum-example/093-compile-sfc-script)
Browse files Browse the repository at this point in the history
  • Loading branch information
ubugeeei committed Dec 14, 2024
1 parent 921f472 commit 60f6ebc
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 19 deletions.
31 changes: 22 additions & 9 deletions book/online-book/src/10-minimum-example/093-compile-sfc-script.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default {
I want to extract only the following part:

```ts
{
{
setup() {},
}
```
Expand Down Expand Up @@ -61,7 +61,8 @@ interface Program {
}
```

Statement represents a "statement" in JavaScript, which is a collection of statements. Examples include "variable declaration statement," "if statement," "for statement," and "block statement."
Statement represents a "statement" in JavaScript, which is a collection of statements. \
Examples include "variable declaration statement," "if statement," "for statement," and "block statement."

```ts
interface Statement {}
Expand All @@ -84,7 +85,9 @@ interface BlockStatement extends Statement {
// There are many more
```

Statements usually have an "expression" in most cases. An expression is something that can be assigned to a variable. Examples include "object," "binary operation," and "function call."
Statements usually have an "expression" in most cases. \
An expression is something that can be assigned to a variable. \
Examples include "object," "binary operation," and "function call."

```ts
interface Expression {}
Expand Down Expand Up @@ -117,22 +120,30 @@ interface IfStatement extends Statement {
}
```

In this way, JavaScript syntax is parsed into the AST mentioned above. I think this explanation is easy to understand for those who have already implemented the template compiler for chibivue. (It's the same thing)
In this way, JavaScript syntax is parsed into the AST mentioned above. \
I think this explanation is easy to understand for those who have already implemented the template compiler for chibivue. (It's the same thing)

The reason why I use Babel is twofold. First, it's simply because it's cumbersome. If you have implemented a parser before, it may be technically possible to implement a JS parser while referring to estree. However, it is very cumbersome, and it is not very important for the purpose of "deepening understanding of Vue" in this case. The other reason is that the official Vue also uses Babel for this part.
The reason why I use Babel is twofold.\
First, it's simply because it's cumbersome. \
If you have implemented a parser before, it may be technically possible to implement a JS parser while referring to estree. \
However, it is very cumbersome, and it is not very important for the purpose of "deepening understanding of Vue" in this case. \
The other reason is that the official Vue also uses Babel for this part.

### magic-string

https://github.com/rich-harris/magic-string

There is another library I want to use. This library is also used by the official Vue. It is a library that makes string manipulation easier.
There is another library I want to use. \
This library is also used by the official Vue. \
It is a library that makes string manipulation easier.

```ts
const input = 'Hello'
const s = new MagicString(input)
```

You can generate an instance like this and use the convenient methods provided by the instance to manipulate strings. Here are some examples:
You can generate an instance like this and use the convenient methods provided by the instance to manipulate strings. \
Here are some examples:

```ts
s.append('!!!') // Append to the end
Expand All @@ -142,7 +153,8 @@ s.overwrite(9, 13, 'こんにちは') // Overwrite within a range

There is no need to use it forcefully, but I will use it to align with the official Vue.

Whether it's Babel or magic-string, you don't need to understand the actual usage at this point. I will explain and align the implementation later, so it's okay to have a rough understanding for now.
Whether it's Babel or magic-string, you don't need to understand the actual usage at this point. \
I will explain and align the implementation later, so it's okay to have a rough understanding for now.

## Rewriting the default export of the script

Expand Down Expand Up @@ -336,7 +348,8 @@ function specifierEnd(input: string, end: number, nodeEnd: number | null) {
}
```

Now you can rewrite the default export. Let's try using it in a plugin.
Now you can rewrite the default export. \
Let's try using it in a plugin.

```ts
import type { Plugin } from 'vite'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ interface Program {
}
```

Statement というのは日本で言うと「文」です.JavaScript は文の集まりです.具体的には「変数宣言文」や「if 文」「for 文」「ブロック」などが挙げられます.
Statement というのは日本で言うと「文」です.JavaScript は文の集まりです.\
具体的には「変数宣言文」や「if 文」「for 文」「ブロック」などが挙げられます.

```ts
interface Statement {}
Expand All @@ -86,7 +87,9 @@ interface BlockStatement extends Statement {
// 他にもたくさんある
```

そして,文というのは多くの場合「Expression(式)」を持ちます.式というのは変数に代入できる物だと考えてもらえれば良いです.具体的には「オブジェクト」や「2 項演算」「関数呼び出し」などが挙げられます.
そして,文というのは多くの場合「Expression(式)」を持ちます.\
式というのは変数に代入できる物だと考えてもらえれば良いです.\
具体的には「オブジェクト」や「2 項演算」「関数呼び出し」などが挙げられます.

```ts
interface Expression {}
Expand Down Expand Up @@ -119,10 +122,13 @@ interface IfStatement extends Statement {
}
```

このように,JavaScript の構文は上記のような AST にパースされるのです.既に chibivue のテンプレートのコンパイラを実装したみなさんにとっては分かりやすい話だと思います.(同じこと)
このように,JavaScript の構文は上記のような AST にパースされるのです.\
既に chibivue のテンプレートのコンパイラを実装したみなさんにとっては分かりやすい話だと思います.(同じこと)

なぜ Babel を使うのかというと,理由は2つあって,1 つは単純にめんどくさいからです.パーサを実装したことあるみなさんなら estree を見ながら JS のパーサを実装することも技術的には可能かも知れません.
けど,とてもめんどくさいし,今回の「Vue の理解を深める」という点においてはあまり重要ではありません.もう一つの理由は本家 Vue もこの部分は Babel を使っているという点です.
なぜ Babel を使うのかというと,理由は2つあって,1 つは単純にめんどくさいからです.\
パーサを実装したことあるみなさんなら estree を見ながら JS のパーサを実装することも技術的には可能かも知れません.\
けれども,とてもめんどくさいし,今回の「Vue の理解を深める」という点においてはあまり重要ではありません.\
もう一つの理由は本家 Vue もこの部分は Babel を使っているという点です.

### magic-string

Expand All @@ -136,7 +142,7 @@ const input = 'Hello'
const s = new MagicString(input)
```

のようにインスタンスを生成し,そのインスタンスに生えている便利なメソッドを利用して文字列操作をしていきます.
のようにインスタンスを生成し,そのインスタンスに生えている便利なメソッドを利用して文字列操作をしていきます.\
いくつか例をあげます.

```ts
Expand Down Expand Up @@ -241,8 +247,8 @@ export function rewriteDefault(input: string, as: string): string {
}
```

ここからは Babel パーサによって得られた JavaScript の AST(ast) を元に s を文字列操作していきます.
少し長いですが,ソースコード内のコメントで補足の説明も入れていきます.
ここからは Babel パーサによって得られた JavaScript の AST(ast) を元に s を文字列操作していきます.\
少し長いですが,ソースコード内のコメントで補足の説明も入れていきます.\
基本的には AST を手繰っていって,type によって分岐処理を書いて magic-string のメソッドで s を操作していくだけです.

```ts
Expand Down Expand Up @@ -343,7 +349,8 @@ function specifierEnd(input: string, end: number, nodeEnd: number | null) {
}
```

これで default export の書き換えができるようになりました.実際に plugin で使ってみましょう.
これで default export の書き換えができるようになりました.\
実際に plugin で使ってみましょう.

```ts
import type { Plugin } from 'vite'
Expand Down Expand Up @@ -405,7 +412,7 @@ export const setupComponent = (instance: ComponentInternalInstance) => {
}
```

これでレンダリングができるようになっているはずです!!
これでレンダリングができるようになっているはずです!!

![render_sfc](https://raw.githubusercontent.com/chibivue-land/chibivue/main/book/images/render_sfc.png)

Expand Down

0 comments on commit 60f6ebc

Please sign in to comment.