スクラッチからWebpack+Babel+Vue.jsを使う をVue 3に対応させてみました。
Vue CLI も Rails+Webpacker も使わずに、Vue.js(Single File Component)のバージョン3を試す方法です。スクラッチから作るのが好きな人、WebpackとBabelが吐いたコードを眺めたい人はどうぞ。
準備
てきとうなディレクトリを作り、yarnで必要なモジュールをインストールします。
% mkdir scratch && cd scratch
% yarn add @babel/core @babel/preset-env babel-loader core-js vue@next vue-loader@next @vue/compiler-sfc vue-template-compiler webpack webpack-cli
vue と vue-loader をVue 3のものにするために vue@next
、vue-loader@next
とします。また、vue-loader を動かすのに @vue/compiler-sfc
が必要です。
最終的なディレクトリとファイルの配置は次のようになります。
- dist
- app.js
- app.js.map
- node_modules
- src
- app.js
- hello.vue
- babel.config.js
- index.html
- package.json
- wbpack.config.js
- yarn.lock
Vueアプリケーション
HTMLと簡単なVueアプリケーションを書きます。Vue 2との違いは、アプリケーションを作成してマウントする部分 createApp(Hello).mount('#app');
だけです。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>てすと</title>
<script src="dist/app.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
import "core-js/stable";
import "regenerator-runtime/runtime";
import { createApp } from 'vue';
import Hello from './hello.vue';
document.addEventListener('DOMContentLoaded', () => {
createApp(Hello).mount('#app');
});
<template>
<div>
<h1>{{message}}</h1>
<p><input v-model="message"></p>
</div>
</template>
<script>
export default {
data() {
return {
message: ''
};
},
created() {
this.message = 'hello';
}
}
</script>
webpack.config.js
webpack.config.js を書きます。src/app.js が dist/app.js に出力されるようにします。
const { VueLoaderPlugin } = require('vue-loader');
const webpack = require('webpack');
const path = require('path');
const env = process.env.NODE_ENV || 'development';
module.exports = {
entry: './src/app.js',
output: {
filename: 'app.js',
path: path.resolve(__dirname, 'dist'),
},
devtool: 'source-map',
mode: env,
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader'
}
]
},
plugins: [
new VueLoaderPlugin(),
new webpack.DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false
})
]
}
1行目は、Vue 2では、
const VueLoaderPlugin = require('vue-loader/lib/plugin');
としていたところをVue 3ではちょっと変えます。
const { VueLoaderPlugin } = require('vue-loader');
plugins: のところで、2つのオプションを指定していますが、これがないと実行時にWarningが出ます(Bundler Build Feature Flags を参照)。
new webpack.DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false
})
babel.config.js
IE 11対応にするために、babel.config.js に preset-env の設定を書きます。ここは Vue 2のものから変えていません。
module.exports = api => {
api.cache(true);
return {
presets: [
[
"@babel/preset-env",
{
targets: { ie: "11" },
useBuiltIns: "entry",
corejs: 3
}
]
]
}
}
コンパイル
package.json に scripts.build を追加すると、yarnコマンドでwebpackを呼び出せます。
{
"scripts": {
"build": "webpack --config=webpack.config.js"
},
"dependencies": {
"@babel/core": "^7.12.3",
"@babel/preset-env": "^7.12.1",
"@vue/compiler-sfc": "^3.0.2",
"babel-loader": "^8.1.0",
"core-js": "^3.6.5",
"vue": "^3.0.2",
"vue-loader": "^16.0.0-beta.8",
"vue-template-compiler": "^2.6.12",
"webpack": "^5.2.0",
"webpack-cli": "^4.1.0"
}
}
yarn build とすると、webpackが dist/app.js を生成します。
% yarn build
環境変数 NODE_ENV を production にすると、本番環境用に圧縮された dist/app.js ができます。
% NODE_ENV=production yarn build
index.html を ブラウザーで開いてVueアプリケーションが動けば成功です。
2020-12-15 追記: app.js に以下の2行を入れても、Vue 3はIE 11で動きません。「catch ステートメントでは適用されますが、throw ステートメントでは適用されません。」のエラーが出ます(throw TypeError
が引っかかる)。core-jsで発生するエラーのようです( https://github.com/zloirock/core-js/issues/514 )。core-jsを最新版に上げてもダメでした。
import "core-js/stable";
import "regenerator-runtime/runtime";