VueとWebpackとJestの最初の一歩

Lachlan Miller
12 min readAug 20, 2017

--

Vue, node, webpackとJestで簡単なアプリを作ります。vue-cli というツールを使ってテンプレートから始めるのが便利ですが、設定をはっきり理解して欲しいので、vue-cli を使わずに少しずつスタックを作成します。Vue, node (express), webpack, jestを使います。

ソースコード:https://github.com/lmiller1990/vue-webpack-jest-express

Node, babel, es6をインストール

まずは、babel をインストールします。

yarn add --dev babel-preset-env babel-cli

babelは、ES6、ES7などの新しいJavaScriptの機能を一般的なブラウザがサポートしているES5にコンパイルするプログラムです。

babelを使うため、.babelrc というファイルを作成して、その中に以下の通り入力します。

{ 
"presets": [
"env"
]
}

package.json を更新します。

"scripts": {
"start": "babel-node src/index.js"
"

次が、srcというディレクトリを作成して、その中にserverというのを作ります。serverの中にindex.js, hello.jsというファイルを作成します。

src/server/index.js

import hello from './hello'console.log(hello())

src/server/hello.js

function hello() {
return 'Hello from babel'
}
export default hello

yarn start を実行します。

Hello from babel が表示されるはずです。表示されたら、babelを実行していることになります。

Jestをインストール

次は、Jestをインストールして、簡単なテストを書いてみましょう。

yarn add --dev jest

package.json を更新します:

"scripts": {
"start:" "babel-node src/server/index.js",
"test": "jest"
}

src/server/hello.test.js というファイルを作ります。.testがファイルネームに入ったら、Jestは自動に実行します。

src/server/hello.test.js

import hello from './hello'test('it says hello', () => {
expect(hello()).toBe('Hello from babel')
})

yarn test で実行します。

PASS  src/server/hello.test.js
✓ it says hello (5ms)

上記の内容が表示されるはずです。

Node (express)のサーバー

VueアプリをHTTPサーバーでサーブします。有名なExpress.jsを使います。

yarn add express

でインストールしてから、src/server/index.js を更新します。

import express from 'express'import renderApp from './renderApp'const app = express()app.get('/', (req, res) => {
res.send(renderApp())
})
app.listen(3000, () => console.log('Listening on port 3000.'))

import hello from './hello' はいりません。これは、Jestとbabelをちゃんと動かせるのを確認するためだけのものです。

src/server/renderApp.js を作ります。

const renderApp = () =>
`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h3>Hello from express</h3>
<div id="app"></div>
</body>
</html>
`
export default renderApp

まだ作っていないけれど、<div id="app"></div> をVueアプリを載せるタグです。

yarn start で実行します。ブラウザーでhttp://localhost:3000にアクセスすると、Welcome to expressが表示されるはずです。

Webpackでファイルをまとめる

Webpackでたくさんのファイルをまとめるモジュールバンドラーです。Webpackを使って、別のファイル(.vue, .jsなど)を全部一つのファイルにまとめて、クライアントに送ります。

今まで、サーバーサイドコードだけを書きました。

src/client というディレクトリを作って、その中にindex.js を作ります。index.js が二つあります。一つ目は、サーバーの。もう一つは、クライアントのです。src/client/index.js 以下通り入力してください。

document.querySelector('#app').innerHTML = '<h3>Hello from webpack</h3>'

次は、ルートに

webpack.config.babel.js を作ります。

import path from 'path'
import webpack from 'webpack'
export default {
entry: [
'./src/client/index.js'
],
output: {
filename: 'js/bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: `http://localhost:8000/dist/`,
},
module: {
rules: [
{
test: /\.vue$/, loader: 'vue-loader', options: {
loaders: {
js: 'babel-loader'
}
}
},
{
test: /\.js/, use: 'babel-loader', exclude: /node_modules/
}
]
},
devtool: 'source-map',
resolve: {
extensions: ['.js', '.vue']
},
devServer: {
port: 8000,
hot: true,
headers: {
'Access-Control-Allow-Origin': '*',
}
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
}

そして、webpackと必要なモジュールをインストールします。この設定は別の投稿で説明します 。devServer というのは、まとめたbundle.jsをlocalhost:8000でアクセスできるサーバーでサーブします。これを使うと開発が早くなります。続きを見ればわかります。

webpackとコンパイルに必要あモジュールをインストールします。nodemon をインストールします。nodemonを利用すれば、サーバーのファイルを手動で更新することなく、自動で再起動します。

yarn add --dev webpack webpack-dev-server babel-core babel-loader vue-loader css-loader
yarn global add nodemon

webpack を実行してみます。dist/js/bundle.js が作成されるはずです。最後の一行は、document.querySelector(‘#app’).innerHTML = ‘<h3>Hello from webpack</h3>’; .

そして、まとめたbundle.js をアプリに表示しましょう。src/server/renderApp.js を更新します。

<!-- ここまで同じ -->
<body>
<h3>Hello from express</h3>
<div id="app"></div>
<script src="http://localhost:8000/dist/js/bundle.js"></script>
</body>

package.json にwebpackのタスクを追加します。start も更新します。

"scripts": {
"dev:wds": "webpack-dev-server --progress",
"nodemon -e .vue,.js --ignore lib,files --exec babel-node src/server/index.js
}

一番目のターミナルでyarn start を実行して、もう一つのターミナルでyarn dev:wds を実行します。http://localhost:3000にアクセスと、

Hello from express

Hello from webpack

が表示されるはずです。webpack-dev-serverから読み込んでいます。さらに、webpack-dev-server を使っているので、src/client のファイルを更新して、セーブすると自動にページがリフレッシュします。

Vueを統合します

Vueを統合しましょう。src/client/App.vue を作ります。

<template>
<div>
<div class="greeting">
Hello Vue
</div>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style scoped>
</style>

Vueで開発する際は、こういうテンプレートを作ることが多いです。私はこのモジュールを作って、vc App.vue だけで以上のようなテンプレートが作成されます。

src/client/index.js を更新します。

import Vue from 'vue'import App from './App'new Vue({
el: '#app',
render: h => h(App),
template: '<App />',
components: { App }
})

そして、Vueをインストールします。

yarn add vue

yarn dev:wds をまた実行します。Hello Vueをブラウザに表示されるはずです。

JestでVueコンポーネントをテストする

Jestで、.vue コンポーネントを簡単にテストできます。.vue を読み込むために、jest-vue-preprocessor を使います。

yarn add --dev jest-vue-preprocessor

そして、package.jsonjest という新しい部分を追加します。

"jest": {
"moduleFileExtensions": [
"js",
"vue"
],
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/babel-jest",
".*\\.(vue)$": "<rootDir>/node_modules/jest-vue-preprocessor"
}
}

src/client/App.test.js を作ります。

import Vue from 'vue'
import App from './App.vue'
const doTest = (Component) => {
const vm = new Vue({
el: document.createElement('div'),
render: h => h(Component)
})
expect(vm.$el.querySelector('.greeting')
.textContent.trim()).toEqual('Hello Vue')
}
describe('App.vue', () => {
it('should load a .vue file', () => {
doTest(App)
})
})

yarn test で実行します。大丈夫なはずです。

最後に、もう一つのテストを書いてみます。

src/client/Clicker.vue を作成します。src/client/Clicker.test.js も。

src/client/Clicker.vue

<template>
<div>
Count: {{ count }}
<button @click="clicked">Click me</button>
</div>
</template>
<script>
export default {
name: 'Tester',

data() {
return {
count: 0
}
},
methods: {
clicked() {
this.count += 1
}
}
}
</script>
<style scoped>
</style>

localhost:3000にアクセスして、ボタンを押してみましょう。count が1ずつ増えます。テストをしましょう!

import Vue from 'vue'
import Tester from './Tester.vue'
const doTest = (Component) => {
const vm = new Vue({
el: document.createElement('div'),
render: h => h(Component)
})
vm.$el.querySelector('button').click()

expect(vm.$children[0].count).toBe(1)
}
describe('Tester.vue', () => {
it('should increment a counter when a button is clicked', () => {
doTest(Tester)
})
})

大丈夫なはずです。

今度は、非同期に実行するコードなどをテストしたいです。

ソースコード:https://github.com/lmiller1990/vue-webpack-jest-express

--

--

Lachlan Miller

I write about frontend, Vue.js, and TDD on https://vuejs-course.com. You can reach me on @lmiller1990 on Github and @Lachlan19900 on Twitter.