JSひろばアプリもほぼ完成に近づいていきました。今日は最終的にvue-routerを入れて、URLで指定したコードのIDをコンソールに貼り付けできるようにします。これで、これからJSのチュートリアルを作成する際にリンクを貼り付けて、そこからサンプリコードを実行できるようにすることが目的です。
今後はユーザーがコードを登録できたり、シェアできるようにできたら楽しいなと思います。オープンソースなので皆さんでカスタマイズして試してください。
作業日 | 2022年12月28日 |
作業にかけた時間 | 6時間 |
合計作業時間 | 30時間 |
作業内容 | モジュールインポートエラーの対応 favアイコンの作成 英語版に対応させる DBモデルの改修 Google Analyrticsの追加 ローディング画面の設定 Vue-routerの追加 |
モジュールインポートエラーの対応
Vueアプリをnpm run buildのコマンドでプロダクション用にコンパイルするとデプロイしようとすると下記のエラーが出ました。
[vite]: Rollup failed to resolve import "highlight.js/scss/github-dark.css" from "src/App.vue". This is most likely unintended because it can break your application at runtime. If you do want to externalize this module explicitly add it to `build.rollupOptions.external` error during build: Error: [vite]: Rollup failed to resolve import "highlight.js/scss/github-dark.css" from "src/App.vue". This is most likely unintended because it can break your application at runtime. If you do want to externalize this module explicitly add it to `build.rollupOptions.external` at onRollupWarning (file:///home/dan/JS-Hiroba/node_modules/vite/dist/node/chunks/dep-5605cfa4.js:45832:19) at onwarn (file:///home/dan/JS-Hiroba/node_modules/vite/dist/node/chunks/dep-5605cfa4.js:45603:13) at Object.onwarn (file:///home/dan/JS-Hiroba/node_modules/rollup/dist/es/shared/rollup.js:23263:13) at ModuleLoader.handleResolveId (file:///home/dan/JS-Hiroba/node_modules/rollup/dist/es/shared/rollup.js:22158:26) at file:///home/dan/JS-Hiroba/node_modules/rollup/dist/es/shared/rollup.js:22119:26
調べてみると、npmでインストールしたハイライトのプラグインのCSSをインポートしていることが原因の様でした。rollupでモジュール内のCSSをエクスターナルのファイルとして特例で設定しないといけないようです。

vite.config.jsで下記の様にbuildの部分を追加して再度npm run buildを実行したところ、問題が解決できました。
import { fileURLToPath, URL } from "url"; import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], resolve: { alias: { "@": fileURLToPath(new URL("./src", import.meta.url)), }, }, build: { rollupOptions: { // https://rollupjs.org/guide/en/#big-list-of-options external: [/^node:.*/], }, }, });
favアイコンの作成
Adobeのイラストレーターでブックマークに使われるアイコンを作りました。SVGで作成したのでデスクトップのブックマークでも画像がぼやけないようにしました。
英語版に対応させる
日本語だけだとユーザーが限られるので英語版に対応したアプリにさせます。このようにToggle(トグル)させるボタンをつくりRefでisJapaneseがtrueかfalseかを判定させるようにしました。このデータはPiniaに保管されグローバルにアクセスできるようにしています。

DBモデルの改修
では英語版に対応したデータがないのでDjangoのモデルを追加します。英語用のフィールドと難易度をチョイスで追加しました。
class Command(models.Model): DIFFICULTY_CHOICES = [ ('Easy', 'Easy'), ('Intermediate', 'Intermediate'), ('Difficult', 'Difficult'), ('Not Rated', 'Not Rated'), ] title = models.CharField(max_length=300, blank=True, null=True) keyword = models.CharField(max_length=100, blank=True, null=True) command = models.TextField(max_length=300, blank=True, null=True) title_en = models.CharField(max_length=300, blank=True, null=True) difficulty = models.CharField( max_length=20, choices=DIFFICULTY_CHOICES, default="Not Rated", ) class Meta: verbose_name_plural='Commands' def __str__(self): return self.title
Google Analyticsの追加
Google Analyticsを追加しました。特に説明する必要はないと思いますが、headタグ内に用意されたscriptを配置しただけでOKです。
難易度のフィルター
次にコマンドの例を初級、中級、上級に分けてソートする機能を付けました。
ボタンが順番に表示されるようになり、それに合わせてデータがフィルターされます。

Vue-Routerの追加
最後に、データベースから引っ張ってきたコードはIDでURLの最後にくっつけます。これでブログとかでコードを指定して表示させたい場合は、URLでそのまま引用できるようになります。
npm install vue-router@4 #mian.jsに追加 import router from "./router"; const app = createApp(App); app.use(router);
で、検索されたコマンドがペーストされた後に、URLにIDを飛ばしました。
import { useRouter, useRoute } from "vue-router"; const emitSearchPaste = (data) => { resetCommand(); router.push({ name: 'command', params: { id: data.id } }) consoleValue.value = data.command; mainMsg.msg = data.title; mainMsg.msgEn = data.title_en; closeDialog(); };
URLを監視する
Vue-Routerを使う一番の理由である、URLから目的のコードをコピペされた状態にするということを達成するために、watchEffect()を使いました。
// Update console value with URL param const updateConsole = (commandId) => { let currentCommand = store.keywordData.find((el) => el.id == commandId); mainMsg.msg = currentCommand.title; mainMsg.msgEn = currentCommand.title_en; return (consoleValue.value = currentCommand.command); }; // Update IF URL CHANGES watchEffect(() => { if (store.keywordData && route.params.id) { updateConsole(route.params.id); } })
これでアプリのイニシャライゼーション(初期読込)の時とURLが変わったときにフェッチしたデータをコンソールにペーストできるようになりました。
とりあえず完成とします。あとは、Django側でデータを入れて、JSの記事に使えるか試してみます。
お疲れ様です。