【Vue.js】コンパイラってよく聞くけど一体全体なんなんだ!?!?!?
🚩 初めに
こんにちは。Vue Beginners です! 😄
これまでに、Vue の勉強を始める方法や、環境構築の方法などを紹介してきました。
今回はもう少し範囲を絞って、具体的な疑問について解説していきます!!!!!
Vue.js について学んでいると、コンパイラ という言葉を見かけることがあると思います。
皆さんは「Vue.js のコンパイラとは何ですか?」と聞かれたら、どのように答えますか? 🤔
意外と戸惑う方も多いのではないでしょうか。
今回はコンパイラとは何なのか、何のためにあるのか、Vue.js のコンパイラとはどういうものなのかについて説明してみます。
それではスタート!!!!!!!!!!!
🤔 コンパイラとは
これからの説明は、Vue.js に限った話ではありません。
プログラミング全般で使われる コンパイラ という意味について説明していきます。
コンパイラ (Compiler) は、日本語で「翻訳機」という意味です。
完結にいうと、「あるソースコードをあるソースコードに変換するもの」です。
具体例を挙げると、
- Vue コンパイラ
- C コンパイラ
- Rust コンパイラ
などです。
ここで注意したいことは、この変換というのはめちゃくちゃに変換するという意味ではなくて、意味を変えずに変換する という意味だということです。
ではどうしてそんなことが必要なのでしょうか?
存在意義
コンパイラの存在意義は端的にいうと 「DX を向上させるため」 が大きな部分を占めています。
DX というのは Developer Experience の略で、開発者の体験を指します。
ここでいうと実際に Vue や C, Rust などのソースコードを書いて開発する人の体験を指します。
プログラミング以外の文脈でも、あのサービスは体験がいい。なんて言い方をしますよね。ここでは「書き心地」ということです。
それでは、書き心地、というのは何によるものなのでしょうか?
いくつかあるので紹介します。
※ まずは C, Rust などのプログラミング言語での例です。
1. 記述の簡略化・意味付け
まず前提として、「機械にとって分かりやすいソースコードの形式」と「人間とって分かりやすいソースコードの形式」というのは異なります。
まず、ソースコードというと皆さんは以下のようなものを想像するかもしれません。
#include <stdio.h>
int main() {
int a = 5;
if (a > 0) {
printf("a is positive");
} else {
printf("a is negative");
}
return 0;
}
// ※ これは C 言語のコードですが、あまり気にしないでください。
しかしこれは実は人間にとって分かりやすい形式で、機械にとっては分かりにくい形式です。
if
else
なんてものは機械にとってはただの文字列なので、これを機械が勝手に良しなに理解してくれることはありません。
さて。それでは機械にとって分かりやすい形式というものはどういうものでしょうか?
試しに見てみます。(一部省略)
6923 636e 756c 6564 2220 7473 6964 2e6f
2268 0a0a 6e69 2074 616d 6e69 2928 7b20
200a 2020 6920 746e 6120 3d20 3520 0a3b
2020 2020 6669 2820 2061 203e 2930 7b20
200a 2020 2020 2020 7020 6972 746e 2866
6122 6920 2073 6f70 6973 6974 6576 2922
0a3b 2020 2020 207d 6c65 6573 7b20 200a
2020 2020 2020 7020 6972 746e 2866 6122
6920 2073 656e 6167 6974 6576 2922 0a3b
2020 2020 0a7d 200a 2020 7220 7465 7275
206e 3b30 7d0a 000a
はい、全く意味がわかりません。(※一部の猛者は意味を理解できることが知られています)
プログラムというのは数値の羅列で、この数値一つ一つが命令として定義されているのです。
では、私たちが普段開発する際に、すべてこの数値の羅列でプログラムを書きたいでしょうか?
・
・
・
そんなことは絶対に嫌ですよね......
そこで、人間にとってわかりやすい形式を定義して、それを機械が理解できる形に変換するためのツールを作ります。
このツールこそが コンパイラ です。
後ほど Vue.js の話をしますが、今までの話は 人間 -> コンピュータ の話であることに注意してください。(Vue の場合は少し異なります)
2. 最適化
コンパイラは記述の簡略化以外の観点でも仕事をしています。
それが 最適化 です。最適化とは何でしょうか?
最適化とはざっくり「プログラムのパフォーマンスを向上させること」です。
不要な処理を省略してパフォーマンスを向上させます。
この、不要な処理を省略する という作業も一部コンパイラが行います。
もちろん、全てのパフォーマンス向上をコンパイラが良しなにやってくれるわけではないですが、
一部そういうこともやってくれている、というくらいの意味です。
(もしかすると、いちいち最適なコードを考えなくて良いという意味では記述の簡略化と言えるかもしれません)
🤔 Vue.js におけるコンパイラというものはどういうものなのか
ここまで、人間の為のソースコード (C など) と 機械(コンピュータ) の為のソースコード (数値の羅列) という対象について説明してきました。
Vue.js では少し対象が違います。
Vue.js のコンパイラは 人間の為のソースコード (Vue コンポーネント) から、ブラウザの為のソースコード (JavaScript (と CSS)) に変換する為のものです。
そう、 人間 -> ブラウザ です。
前提として、ブラウザ上で動くものは HTML/CSS/JavaScript だけである ということを覚えておいてください。(実際には wasm などもありますが、関係ないので割愛します。)
しかし Vue のコンポーネントを見てみましょう。
<script setup lang="ts">
import { ref } from "vue";
const message = ref("Hello, Vue!");
function changeMessage() {
message.value = "Clicked!";
}
</script>
<template>
<div>
<h1>{{ message }}</h1>
<p>content content content</p>
<button type="button" @click="changeMessage()">Click me</button>
</div>
</template>
いかがでしょうか?
全然 HTML/CSS/JavaScript だけ とはいえません。
-
<script setup>
という記法 -
<template>
という記法 -
{{ message }}
という記法 -
@click="changeMessage"
という記法
明らかに HTML/CSS/JavaScript ではないものが登場しています。
これを HTML/CSS/JavaScript (ブラウザが理解できる形式) に変換するためのものが Vue コンパイラ です。
つまり、Vue.js のコンパイラは、「人間が快適に Web アプリケーションを書くために独自の記法を定義し、コンパイラによってブラウザが理解できかつ効率の良いコードにコンパイルする」という仕事をしています。
実際に SFC Playground で出力された JavaScript を見てみることができます。
/* Analyzed bindings: {
"ref": "setup-const",
"message": "setup-ref",
"changeMessage": "setup-const"
} */
import { defineComponent as _defineComponent } from "vue";
import { ref } from "vue";
const __sfc__ = _defineComponent({
__name: "App",
setup(__props, { expose: __expose }) {
__expose();
const message = ref("Hello, Vue!");
function changeMessage() {
message.value = "Clicked!";
}
const __returned__ = { message, changeMessage };
Object.defineProperty(__returned__, "__isScriptSetup", {
enumerable: false,
value: true,
});
return __returned__;
},
});
import {
toDisplayString as _toDisplayString,
createElementVNode as _createElementVNode,
openBlock as _openBlock,
createElementBlock as _createElementBlock,
} from "vue";
const _hoisted_1 = /*#__PURE__*/ _createElementVNode(
"p",
null,
"content content content",
-1 /* HOISTED */
);
function render(_ctx, _cache, $props, $setup, $data, $options) {
return (
_openBlock(),
_createElementBlock("div", null, [
_createElementVNode(
"h1",
null,
_toDisplayString($setup.message),
1 /* TEXT */
),
_hoisted_1,
_createElementVNode(
"button",
{
type: "button",
onClick:
_cache[0] || (_cache[0] = ($event) => $setup.changeMessage()),
},
"Click me"
),
])
);
}
__sfc__.render = render;
__sfc__.__file = "src/App.vue";
export default __sfc__;
style タグがある場合は CSS が出力されますが、ほぼ全て JavaScript に変換されます。
HTML のよう見えていた template も、実は全て JavaScript に変換されています。
これらの JavaScript コードを理解する必要はありません のでご安心ください。
ここで感じて欲しいことは、「確かに全部 JavaScript なのでブラウザ上で動くね」ということと、「う〜ん。複雑で見辛いな」ということです。
このコードはブラウザに寄り添った形式に変換されているので、人間にとって読みづらくて当然です。
逆に、
<script setup lang="ts">
import { ref } from "vue";
const message = ref("Hello, Vue!");
function changeMessage() {
message.value = "Clicked!";
}
</script>
<template>
<div>
<h1>{{ message }}</h1>
<p>content content content</p>
<button type="button" @click="changeMessage()">Click me</button>
</div>
</template>
をみた時に「わかりやすい!!!」と感じることができるのは、コンパイラのおかげです。
これで「Vue.js のコンパイラというものがどういうものなのか?」について何となく理解できたのではないでしょうか?
🥅 まとめ!
コンパイラとは
人間にとってわかりやすい記述を、機械のために翻訳してあげる為のツールのことだよ
(※ 実は機械のためとも限りません. 人間 to 別の人間 ということなどもありえます.)
Vue.js のコンパイラとは
快適に Web アプリケーションを書くための記法を、ブラウザが理解できかつ効率の良いコードに翻訳してあげるためのツールのことだよ
具体的には、Single File Component を JavaScript に変換するためのものだよ. (場合によっては CSS も出力するよ)
参考文献:
Discussion