poi上で作ったvueコンポーネントをLaravelプロジェクトに載っけようとしたらエラーが出る
Vueはコンポーネントの遅延ローディングをサポートしていますが、poiでは何もしなくても動いた構文がLaravel5.5ではビルドエラーになってしまいます
コンポーネントの動的読み込み部分で以下の様なエラーが出ます
ERROR in ./node_modules/babel-loader/lib?{"cacheDirectory":true,"presets":[["env",{"modules":false,"targets":{"browsers":["> 2%"],"uglify":true}}]],"plugins":["transform-object-rest-spread",["transform-runtime",{"polyfill":false,"helpers":false}]]}!./node_modules/vue-loader/lib/selector.js?type=script&index=0&bustCache!./resources/assets/js/components/sample_switch_smoothly/SwitchSmoothly.vue
Module build failed: SyntaxError: Unexpected token (38:20)
> 38 | const CompB = () => import('./CompB.vue')
| ^
えー何で?Laravelって何もしなくてもES6イケるんじゃないの?
ぐぐってみたら、babelにdynamic import対応プラグインを追加せにゃならんらしい。エーめんどくせ
ここで解決されてたので、それを丸パク参考にしてみる
Vue.js Async Components #1249
% yarn add babel-plugin-syntax-dynamic-import --dev
.babelrc ファイルをプロジェクトrootに作成する。内容は以下の通り
{
"presets": [
[
"env",
{
"targets": {
"browsers": [
"last 2 versions"
]
}
}
]
],
"plugins": ["syntax-dynamic-import"]
}
webpack.mix.js に以下の設定を追加
mix.webpackConfig({
output: {
chunkFilename: 'js/[name].js',
},
});
これでコンパイルエラーも無くなって、ちゃんと2.jsみたいのが出来るのだが、
実行時にそれを読み込もうとする所でエラーになる
エラーは以下
GET http://localhost:8080/[現在の画面のURL]/2.js net::ERR_ABORTED
[Vue warn]: Failed to resolve async component: function compB() {
return __webpack_require__.e/* import() */(2).then(__webpack_require__.bind(null, 115));
}
Reason: Error: Loading chunk 2 failed.
何故相対パスでアクセスするのか・・・馬鹿なの?
webpack.mix.js にpublicPathの設定を追加
mix.webpackConfig({
output: {
chunkFilename: 'js/[name].js',
publicPath: '/',
},
});
やっと動いたー
なんか古いchunkファイルが残るんですけど!
無事に動的importを使ったvueが動作したんですが、# yarn run watch
とか使って開発してると、hot reload関係なのかチャンクファイルがダブります。
0.js, 1.js, 2.js のある状態でvueファイルを編集すると、3.js, 4.js, 5.js が出来ちゃいます。
まあ、デプロイ時には関係ないし開発中も大して実害は無いけども、キモチワルイので対処します。
laravel-mix や babel に出力ファイルを削除してから作る様な設定は無い様子
しょうがないのでnpm scriptに削除タスクを追加(最初の2つ)
jsフォルダには他のファイルもあったりするのでchunksフォルダ以下にチャンクファイルを出力する様に変更
{
"scripts": {
"predevelopment": "npm run clean",
"clean": "rimraf public/js/chunks",
"dev": "npm run development",
"development": "cross-env NODE_ENV=development (略)"
},
}
mix.webpackConfig({
output: {
chunkFilename: 'js/chunks/[name].js', <-- ここを変更
publicPath: '/',
},
});
最後に
poi便利