express + webpack + Babel + Vue.jsでHMRを使いながらIE11対応する
この記事は、「express + webpack + BabelでHMRを使いながらIE11対応する」の記事にVue.jsを追加で組み合わせるための記事であり、重複する内容があります。
expressとは?
Node.jsのフレームワークです。今回は、開発環境向けにWEBサーバを簡単に立ち上げるために使用します。
公式サイト
webpackとは?
複数ファイルに分けて管理しているjs(モジュール)を一つのファイルにまとめてくれるツール(モジュールバンドラー)です。
(正確には1つのファイルとは限りませんが、役割に応じてファイルをまとめられます)
別の記事が参考になります。
Babelとは?
ブラウザがまだ対応していない最新のJavaScriptのソースコードを、ブラウザが対応しているソースコードへ変換してくれるツール (トランスパイラ)です。
別の記事が参考になります。
HMR(Hot Module Replacement)とは?
CSS/JSのソースコードを編集した時に、リロード操作(F5を押す等)無しで編集結果がブラウザに反映される仕組みを提供してくれるwebpackの機能です。
別の記事が参考になります。
Vue.jsとは?
Single Page Application開発等が盛んになってきたことで、フロントエンドの処理やソースコードの複雑さが増し、それを管理するためにMVCのような構造を提供してくれるライブラリやフレームワークが要請されてきました。
その要請に応えるライブラリの一つがVue.jsです。このライブラリは設計におけるビューの部分の構造を提供するライブラリですが、拡張機能を用いれば、フロントエンドでのページルーティングやデータフローの構造を構築しやすくすることが可能です。
今回は複雑なアプリケーションを構築することはせずにVue.jsの
詳しくは公式サイト
expressとwebpackとBabelとVue.jsを組み合わせてHMRを使用した開発をする利点
WEBサーバー(express)からwebpackを使用することで、コマンドラインからwebpackを起動させる必要がなくなり、webpackからBabelを使用することでBabelをコマンドラインから起動させる必要が無くなります。
また、webpackを用いればVue.js独自の拡張子(.vue)を用いたファイルを扱うことが可能になります。 .vueのファイルは、Vue.jsにおけるコンポーネントをファイル単位で管理でき、ソースコードを更に管理しやすくしてくれます。
つまり、コンパイル(モジュール、.vueファイルをバンドル化し、トランスパイルする)工程を自動化させることができます。 そして、HMRを使用することでリロードの作業も省き、開発の高速化が可能になります。
今回は、上記で述べた技術を組み合わせて、IE11に合わせたデモを行います。
手を動かす
以下がインストールされていることを前提とします。
- node.js
- npm
以下が手順概要になります。
- npmでプロジェクトを作成する
- express、webpack、Babel、Vue.js等をインストールする
- 必要なファイルを手動で作成する
- コマンドラインでWEBサーバー(express)を立ち上げる
- IE11でアクセスして確認する
- .vueファイルを編集し、IE11に反映された結果を確認する
1. npmでプロジェクトを作成する
任意のディレクトリで以下のコマンドを実行します。
mkdir express-webpack-babel-vue-hmr-demo
cd express-webpack-babel-vue-hmr-demo
npm init -y
2. express、webpack、Babel、Vue.js等をインストールする
以下のコマンドを実行します。
npm install -D webpack webpack-cli webpack-dev-middleware webpack-hot-middleware
npm install -D babel-loader @babel/core @babel/preset-env
npm install -D vue-loader vue-template-compiler
npm install -S @babel/polyfill express vue
3. 必要なファイルを手動で作成する
以下のファイルを作成します。
- ./index.html
- ./babel.config.js
- ./server.js
- ./webpack.config.js
- ./src/App.vue
- ./src/index.js
以下のようなディレクトリ構造になるはずです。
│ babel.config.js │ index.html │ package.json │ server.js │ webpack.config.js │ ├─node_modules │ └─etc... └─src App.vue index.js
./package.jsonを以下のように書き換えます。
- - "main": "index.js",
- + "private": true,
- + "dev": "node server",
{ "name": "express-webpack-babel-vue-hmr-demo", "version": "1.0.0", "description": "", "private": true, "scripts": { "dev": "node server", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@babel/core": "^7.4.0", "@babel/preset-env": "^7.4.2", "babel-loader": "^8.0.5", "vue-loader": "^15.7.0", "vue-template-compiler": "^2.6.10", "webpack": "^4.29.6", "webpack-cli": "^3.3.0", "webpack-dev-middleware": "^3.6.1", "webpack-hot-middleware": "^2.24.3" }, "dependencies": { "@babel/polyfill": "^7.4.0", "express": "^4.16.4", "lodash": "^4.17.11", "vue": "^2.6.10" } }
./babel.config.jsの内容を次のようにし、babelの動作を設定します。
const presets = [ [ "@babel/env", { targets: { ie: '11' }, useBuiltIns: "usage" } ] ]; module.exports = { presets };
./webpack.config.jsの内容を次のようにし、webpackの動作を設定します。
const webpack = require('webpack'); module.exports = { mode: 'development', entry: ['webpack-hot-middleware/client', './src/index.js'], // 2つのファイルをwebpackの基点とする output: { filename: 'main.js', // 出力されるファイル名 // 出力されるファイルを読み込めるパスを指定する // ファイルはメモリ上に出力され、そのファイルをロードするためのパス // https://webpack.js.org/configuration/output/#outputpublicpath // https://webpack.js.org/guides/public-path/ publicPath: '/example_public_path/' }, module: { rules: [ { test: /\.js$/, // 拡張子が.jsであり exclude: /node_modules/, // ディレクトリがnode_module以外であれば use: ['babel-loader'] // Babelの対象とする }, { test: /\.vue$/, // 拡張子が.vueであり exclude: /node_modules/, // ディレクトリがnode_module以外であれば use: ['vue-loader'] // vueのコンポーネントとしてバンドル対象とする } ] }, resolve: { alias: { // https://jp.vuejs.org/v2/guide/installation.html#ランタイム-コンパイラとランタイム限定の違い 'vue$': 'vue/dist/vue.esm.js' } }, plugins: [ new webpack.HotModuleReplacementPlugin(), // HMRを使用するためのプラグイン new VueLoaderPlugin() // https://vue-loader.vuejs.org/guide/#manual-setup ] };
./server.js
WEBサーバー(express)の動作を記述します。
const express = require('express'); const webpack = require('webpack'); const webpackDevMiddleware = require('webpack-dev-middleware'); const webpackHotMiddleware = require('webpack-hot-middleware'); const WebpackConfig = require('./webpack.config'); const app = express(); const compiler = webpack(WebpackConfig); // メモリ上にファイルをコンパイルする // ファイルを監視して、変更されていれば再コンパイルする app.use(webpackDevMiddleware(compiler, { publicPath: WebpackConfig.output.publicPath, })); // クライアントに変更を通知する // クライアント側でHMRに対応している箇所はリロードせずに更新される app.use(webpackHotMiddleware(compiler)); // index.htmlを静的に配置しているディレクトリを指定する app.use(express.static(__dirname)); const port = process.env.PORT || 8080; app.listen(port, () => { console.log(`Server listening on http://localhost:${port}, Ctrl+C to stop`); });
./index.html
バンドルファイル(main.js)以外に、ブラウザ(IE11)用のポリフィルを読み込んでいます。
webpackからポリフィルもまとめてバンドルしてみたのですが、現在(2019/03/24)では動作が不安定になるため、CDNを使用しました。IE11でHMRが不要な場合はmain.jsのみを残して他は削除してください。
<!doctype html> <html> <head> <title>express + webpack + babel + vueでHMR</title> </head> <body> <div id="app"></div> <script src="https://www.promisejs.org/polyfills/promise-7.0.4.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/event-source-polyfill/0.0.9/eventsource.min.js"></script> <script src="./example_public_path/main.js"></script> </body> </html>
./src/index.js
Appコンポーネント(vueファイルはコンポーネント単位で管理される)を取得し、それを用いてVueのインスタンスを作成しています。
import Vue from 'vue'; import App from './App.vue'; new Vue({ el: '#app', render: h => h(App) });
App.vue
<template> <div id="app"> <div> {{ hello }} </div> </div> </template> <script> export default { data () { return { hello: 'Hello express + webpack + Babel + Vue + HMR' } } } </script> <style lang="sass"> </style>
4. コマンドラインでWEBサーバー(express)を立ち上げる
以下のコマンドを実行して、WEBサーバーを立ち上げます。
npm run dev
上記のコマンドは./package.jsonに定義してあり、以下のコマンドと同等です。
node server
5. IE11でアクセスして確認する
以下のURLにアクセスします。
http://localhost:8080/
以下のように表示されていれば、expressとwebpackとBabelとVue.jsの組み合わせは成功です。
Hello express + webpack + Babel + Vue
6. .vueファイルを編集し、IE11に反映された結果を確認する
WEBサーバーを立ち上げたまま、.vueファイルを編集します。 以下の.vueファイルの\<script>\<\/script>タグの中身を編集して保存します。
./src/App.vue
export default { data () { return { hello: 'Hello express + webpack + Babel + Vue' } } } ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ export default { data () { return { hello: 'Hello express + webpack + Babel + Vue + HMR' // この行を編集 } } }
表示が以下のように即座に変更されればIE11上でのHMRが成功です。
Hello express + webpack + Babel + Vue
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
Hello express + webpack + Babel + Vue + HMR