menu
書いてる野郎
orebike@gmail.com
ついにキタというかやっと入り口というかここからが Vue の始まりのような気がする サーバサイドのビルドである。
このへんからかなりの下準備が必要なお手軽感ゼロ手順が続くがじっくりやっていこう
では進めていこう。
依存関係のある JS ファイル同士を依存関係を解決した状態で1個のファイルに結合して、ブラウザ側からはそのファイルだけ呼び出せば動くようにしたい。
それには webpack というツールを使う。
webpack を駆動するには node.js が必要なので node.js を入れる。
node は ndenv で管理するのが普通のようなので ndenv を入れる。
詳しくはココ参照 Node.js/ndenv/Install
そして node.js を取ってくる
$ ndenv install v11.1.0
では今「ファイラーっぽいUI」の何かがあるディレクトリで
$ ndenv local v11.1.0 $ node --version v11.1.0
こうして、つかえるようにする。
よく出てくる npm というのは node に同梱されているので特にインストールしなくていい。
今から作るいろいろなモノをまとめて管理しておきたいのでその設定ファイルを作る。 作るためのツールや、部品群を依存性を解決してダウンロードするための設定。
その管理ツールが npm というモノ。Javaで言う maven とかに該当する。
設定ファイルを初期化する。
$ npm init
質問がいろいろあるのでそれに答えていくとこういう設定ファイルが1個できあがる
{ "name": "orefiler", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
OK
参考 Node.js/npm
npm を使って「このフォルダ」にインストールする。
$ npm install --save-dev webpack webpack-cli
save-dev というオプションはこのインストールを package.json の開発時の依存として記録しておくということである。 このコマンドを打ったあとで package.json に確かに記録されていることがわかる。 webpack はビルドに使いたいだけで Vue の駆動自体には必要ないので開発時の依存となるわけ。
ローカルにインストトールされたので、node_modules というディレクトリが出来ていてそこに突っ込まれていると思う。
npx という npm に同梱されてくるコマンドを使うと、この node_modules にインストールされたコマンドを実行できる
$ npx webpack -v 4.26.1
やたらグローバルにインストールしたがる人たちが居るが説明が簡単になる以外にほとんど意味は無い。
これで webpack がつかえるようになった。
package.json を見ると今インストールしたものが記録されて、次回の環境再現に準備できていることがわかる。 つまり、このファイルを共有しておけば、手順を踏まなくても一発で構築が完了するということだ。
webpack は glup.js のような何かを実行する何かではなく、明確にjsファイルを統合するという機能のためのツール。 なので Vue とか関係なく、もう普通に書けば普通に統合されるのである。
それでは、src というディレクトリを作ってその中へ今まで作ったファイル群を突っ込もう
では各ソースを紐づけていこう・・・
まず最終的なキック直前となる状態を想定した entry.js を新規に src の中に作る。 つまり、HTML で呼び出された際にこのファイルの状態になっていて欲しいということである。
つまり、index.html に埋め込まれているコードが動く直前状態にまでもっていきたいということである。
ここを眺めると依存性があるのは Vue, store, それと HTML 中に埋め込まれている root-folder コンポーネントである。
var vm = new Vue({ el: "#app", store: store, computed: { rootItems: function(){ return this.$store.state.items; } }, methods: { init: function(){ this.$store.dispatch('initState', ()=>{ this.$mount("#app"); }); } } }); vm.init();
store と root-folder コンポーネントは手元にあるでは Vue.js はどうするか。 これも CDN ではなく npm から取得すればいい
$ npm install --save vue
このようにする。先程の webpack と同様だが、オプションが微妙に違っていて、これは開発時ではなく実行時に依存性がありますよという意味である。
これができたら entry.js が書ける。こうなる
import Vue from 'vue'; import store from './Store'; import RootFolder from './RootFolder'; window.Vue = Vue; window.store = store;
import 変数 form '対象';
という記述で対象の内容をこのファイル中では指定した変数名で扱えるという記述である。 依存性があるもの3つ記述できた、最初の vue は npm で入れたやつで、続く2つが自分で作った Store.js と RootFolder.js である。
import で指定された変数はスコープがこのファイルで閉じているので、最後の index.html の中のスクリプトのために window オブジェクト経由でスコープに穴をあける。
では import store で store に何が入っていてほしいかというと作られた store オブジェクトが入っていてほしい。 ここにインポートされる側にも仕掛けが必要になる。
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); import axios from 'axios'; var store = new Vuex.Store({ // 中略 }); export default store;
このようになる。vuex が必要なのである。先程と同様に入れよう。
$ npm install --save vuex
次の
Vue.use(Vuex)
というのはこの2つが連携する上で必要な記述なようだ。
最後に通信ライブラリの axios 取り込んでいる。これもまだ無いので入れておく
$ npm install --save axios
一番最後に
export default store;
と書かれていて、この記述が import の記述と連動している。 import されたファイルのこの export default 以降に書いてあるオブジェクトが、指定した名前で使用可能になるという仕掛け。
これで entry.js の2つのインポートが終わった。
RootFolder.js に関しても同じ用に記述する。
import Vue from 'vue'; import File from './File'; import Folder from './Folder'; var RootFolder = File.extend({ // 中略 }); Vue.component("root-folder", RootFolder); export default RootFolder;
このコンポーネントは3つのオブジェクトに依存があるのでそれぞれ書く。 最後に、定番の記述で自身を import 側でつかえるように記述している。
これで entry.js の依存性にかんしてすべて解決できた。
RootFolder が File.js に依存しているのでこいつも同様に仕上げる。
import Vue from 'vue'; import ItemName from './ItemName'; import store from './Store'; var File = Vue.extend({ // 中略 }); Vue.component("file", File); export default File;
こんな感じになる。
File は ItemName に依存があるのでこいつも同様に仕上げる。
import Vue from 'vue'; import store from './Store'; var ItemName = Vue.extend({ // 中略 }); Vue.component("item-name", ItemName); export default ItemName;
vue はもうインストールしたし、Store はもう webpack 用に仕上げてあるのでここで終了である。
戻って Folder.js を仕上げる。
import Vue from 'vue'; import File from './File'; var Folder = File.extend({ // 中略 }); Vue.component("folder", Folder); export default Folder;
index.html 内のスクリプトを実行できるを逆算して entry.js を作りその依存性を全部追跡した結果、全部のファイルを import できた。
設定はシンプルでそもそも webpack は js ファイルを1個に統合するツールで今やることは js ファイルを1個の統合するのでそのまんまである。
webpack の設定ファイルはデフォルトで webpack.config.js というファイル名になっていてこの名前で作る。
const path = require('path'); module.exports = { entry: './src/entry.js', output: { filename: 'bundle.js', path: path.resolve(__dirname,'./dist') } };
設定は簡単でどこからスタートするJSを作りたいのかと、その結果を何処に出力するのかだけである。 名前を標準に従って作るならこのファイルすら要らない場合もある。
このようなコマンドを打ってビルドする
$ npx webpack --mode development
これを実行すると dist/bundle.js
というモノが出来上がるはずである。
このファイルに今までの全機能が丸ごと詰め込まれているのでやたら巨大なはずである。
あとはブラウザから読み出すだけ・・・
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Hello</title> <link rel="stylesheet" type="text/css" href="index.css" /> <script src="dist/bundle.js"></script> </head> <body> <div id="app"> <root-folder v-bind:items="rootItems"></root-folder> </div> <script> var vm = new Vue({ el: "#app", store: store, computed: { rootItems: function(){ return this.$store.state.items; } }, methods: { init: function(){ this.$store.dispatch('initState', ()=>{ }); } } }); vm.init(); </script> </body> </html>
しかし・・・動かない
Vue.js では標準では実行ビルドという形でビルドするらしく、テンプレートの解析処理が入っていない。 なので、実行時にこのような警告が出る。
You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
テンプレートを予めコンパイルしてくっつけるか、コンパイラ含みでビルドしろという話。
今回はテンプレートが index.html に埋まっているので webpack 外の話なのでテンプレートコンパイラを内蔵することにする。 このテンプレートコンパイラの内蔵の設定は webpack.config.js にこのように書く。
const path = require('path'); module.exports = { resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' } } entry: './src/entry.js', output: { filename: 'bundle.js', path: path.resolve(__dirname,'./dist') } };
これで再びコンパイルして実行してみると!元通り動いた。 これでサーバサイドでビルドできることがわかった。
このやり方でコンパイラ内蔵の完全ビルドできる理由はよくわからん。