Node-RED と Svelte が連携したプロジェクトに Bootstrap を導入するメモです。
Vue 3 でもやっていたこと
Node-RED と Vue 3 が連携したプロジェクトに初期表示のコンポーネントと Bootstrap を導入するメモ
Bootstrap の導入。この記事と同じことができるよう Svelte のやり方を探っていきます。
やりたいこと
こちらで作ったものをベースに進めます。
Node-RED と Svelte が連携した環境で CSS フレームワーク Bootstrap を適用します。新たにコンポーネントはつくらず、初期表示のコンポーネントに書き加えていきます。
2021/09/15 時点の情報で進めます。
svelte-app フォルダに移動
cd svelte-app
Node-RED 内の Svelteのプロジェクトへ設定するため svelte-app フォルダに移動します。
Bootstrap を適用する
Vue CLI では割と import で呼ぶ感じでしたが、 Svelte では結構自由に入れれるようです。ライトに HTML に CDN で入れる方法でやってみます。これはこれでいいですね!
はじめに · Bootstrap v5.0 を参考に進めていきます。
以下の記事を参考にしました。
- Vue のように import で呼べないときに参考になったもの
- BootstrapVue みたいに Svelte で呼べるアプローチを見て「あ、結構 HTML 内に link タグ入れたりしちゃっていいんだ。Svelte。」って気づいたもの
- 今回は採用しなかったが
@import
使って読んじゃう手もあるんだーと気づいたもの
使うフレームワークが変わると、いろいろな知見に出会えて楽しいですね。
index.html を編集
svelte-app/public/index.html にCSSを加えます。
<!DOCTYPE html> <html lang="en"> <head> <meta charset='utf-8'> <meta name='viewport' content='width=device-width,initial-scale=1'> <!-- Bootstrap 追加 CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous"> <title>Svelte app</title> <link rel='icon' type='image/png' href='/favicon.png'> <link rel='stylesheet' href='/global.css'> <link rel='stylesheet' href='/build/bundle.css'> <script defer src='/build/bundle.js'></script> </head> <body> <div id="app_svelte"></div> <!-- Bootstrap 追加 JavaScript --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script> </body> </html>
Bootstrap の CSS の呼び出は head タグ内に link タグで。また、後述する main.js 内での ID app_svelte の div の中で Svelte 関連の DOM が動くようにするため、 <div id="app_svelte"></div>
を加えつつ、その下に Bootstrap で使う JavaScript を呼び出すことで、実行順を保っています。
main.js を修正
svelte-app/src/main.js に Bootstrap の JavaScript 発動を body 下部で行うための修正をします。
import App from './App.svelte'; var app = new App({ // target: document.body // Bootstrap の JavaScript 発動を body 下部で行うために修正 target: document.getElementById("app_svelte") }); export default app;
document.body でやってしまうと こちら で紹介されている body タグ内に script タグを仕込んだときに発動順が変わってしまうことに気づきました。
ということで、ちょっとだけ改修し、ちゃんと一段下げた ID app_svelte の div の中で Svelte 関連の DOM が動くようにして script タグとの実行の順番を変わらないようにしています。
正しいやり方か若干はっきりしないですが、ひとまずこれで。
App.svelte を編集
svelte-app/src/App.svelte に、Bootstrap 関連の HTML を入れつつ、以下のように記述します。もちろん、以前の <h1>Hello {name}!</h1>
な呼び出しも含めておきます。
<script> let name = 'Node-RED'; // world -> Node-RED </script> <div class="container"> <div class="row"> <div class="row"> <div class="col-sm"> <h1>Hello {name}!</h1> </div> </div> <div class="row"> <div class="col-sm"> <div class="card" style="width: 18rem;"> <div class="card-body"> <h5 class="card-title">Card title</h5> <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6> <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p> <a href="#" class="card-link">Card link</a> <a href="#" class="card-link">Another link</a> </div> </div> </div> </div> <div class="row"> <div class="col-sm"> <ul class="list-group"> <li class="list-group-item">An item</li> <li class="list-group-item">A second item</li> <li class="list-group-item">A third item</li> <li class="list-group-item">A fourth item</li> <li class="list-group-item">And a fifth one</li> </ul> </div> </div> </div> </div>
一旦検証
npm run dev
で確認します。
コンパイルされたログが出て、正常に書きだされたことが分かります。
Bootstrap の CSS が反映され h1 見出しとリストが表示されました。<h1>Hello {name}!</h1>
でデータバインディングしていた name という値が Hello Node-RED! に置き換わっていて Svelte のテンプレート構文もしっかり動いています。
これで、ひととおりの変更できました。
ビルド
npm run build
いよいよ、Node-RED 側から static なフォルダとして見ている svelte-app/public/ フォルダにビルドします。
Node-RED を起動して確認してみる
cd ..
で、Svelte のプロジェクトフォルダから一つ上の階層に上がって
npm run node-red
で、Node-RED を起動して確認してみましょう。
無事、http://127.0.0.1:18801/
でも、同様の表示が確認できました!
Vue 3 と似たやり方に落ち着くかなと思いましたが、やはりちょっと違いましたね。とはいえ、HTML 自体も触りやすく、従来の知識でどこを直せばいいのかが、結構想像しやすいので時間をかけすぎず突破できました~。これは Svelte のいいところですね。