WebpackでVue3+TypeScript+Sass+ESlint+Babelの環境を構築しよう
はじめに
こんにちは、都内でフロントエンドのエンジニアをしているものです。
自己紹介は横に置いておいて Vue3 が2,3週間前ほどに無事リリースされましたね。
Vue3 は従来の Vue2 よりも、TypeScript を適用しやすくなっていて...
というのが今後の活躍に期待できるところです!
React でよくない?というような声も上がっておりますが、プロジェクト構成のそこまで大きくないプロジェクトにおいて有用であったり、レガシープロジェクトからモダンプロジェクトに切り替えるにあたって、React よりも導入コストが低いこともあり、切り替え安いというメリットもあります。
また、Vue はアジア圏内の方々がコミッターに積極的に参加しているなど、見守っていきたいところです。
そこで、モダンなフロント環境でより良い開発体験を得るために、Vue3 + TypeScript のフロント環境を Webpack で構築しようということでこの記事を書くにあたりました。
Webpack の設定や.tsconfig
の設定などで苦労したポイントなどお話しできたらと思います。
この記事の対象者としては以下の方を想定しています。
- フロントエンドの環境構築を少し触ったことがある
- Webpack の環境構築に辛くなったことがある
構成要件
まず、 Webpack の環境として以下を含む構成想定しています。
- Vue3
- TypeScript
- Sass
- ESlint(airbnb)
- Babel
ディレクトリ構成は以下を参考にしてください
準備
必要なモジュールのインストールとnpmスクリプトの設定
まず、package.json
を以下に設定してください。
{
"name": "vue3-tmplate",
"version": "1.0.0",
"description": "",
"main": "main.ts",
"scripts": {
"build-dev": "webpack",
"build-prod": "webpack --env.prod",
"start": "webpack-dev-server",
"lint-check": "./node_modules/.bin/eslint src -c ./.eslintrc --ext ts,tsx,vue; exit 0",
"lint-fix": "./node_modules/.bin/eslint --fix src -c ./.eslintrc --ext ts,tsx,vue; exit 0"
},
"author": "",
"license": "ISC",
"dependencies": {
"vue": "^3.0.0"
},
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/preset-env": "^7.11.5",
"@typescript-eslint/eslint-plugin": "^4.3.0",
"@typescript-eslint/parser": "^4.3.0",
"@vue/compiler-sfc": "^3.0.0",
"babel-loader": "^8.1.0",
"css-loader": "^4.2.2",
"eslint": "^7.10.0",
"eslint-config-airbnb-base": "^14.2.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-vue": "^7.0.0-beta.4",
"eslint-plugin-vue-scoped-css": "^1.0.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.11.2",
"node-sass": "^4.14.1",
"sass-loader": "^10.0.2",
"ts-loader": "^8.0.4",
"typescript": "^4.0.3",
"vue-loader": "^16.0.0-beta.8",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"
}
}
その後、
npm i
を実行します。
とりあえず必要なnpmモジュール
がインストールできました。
npm スクリプトについては、プロダクションビルドと開発環境用のビルドに分け、
vue, ts, tsxファイルに ESlint が当てられるように設定しています。
Babelの設定
Babel 用の設定は一応IE11
に対応できるようにします。
.babelrc
は以下の通りです。
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"ie": 11,
"esmodules": true
},
"useBuiltIns": "usage",
"corejs": 3
}
]
]
}
ESLintの設定
ESLint 用の設定は、Vue3 に適用可能にした上で、Scoped CSS や TS ファイルにも効くようにします。 airbnb の ESlint 設定をほんの少し改造したものを利用します。
.eslintlrc
は以下の通りです。
{
"extends": [
"airbnb-base",
"plugin:@typescript-eslint/recommended",
"plugin:vue/vue3-recommended",
"plugin:vue-scoped-css/vue3-recommended"
],
"plugins": [
"@typescript-eslint",
"vue"
],
"env": {
"node": true,
"es6": true
},
"parser": "vue-eslint-parser", // これがないとVueファイルのtemplateがパースできません
"parserOptions": {
"parser": "@typescript-eslint/parser", // TSファイル用のパーサをここで定義します
"ecmaFeatures": {
"jsx": true
},
"extraFileExtensions": [
"vue", // Vueファイルのパース用に必要です
"ts",
"tsx"
],
"project": "./tsconfig.json", // .tsconfigを読み込みます
"useJSXTextNode": true
},
"rules": {
"import/no-unresolved": "off", // aliasを利用する場合必要です
"semi": "off",
"trailingComma": "off"
}
}
tsconfigの設定
.tsconfig
については以下のように記述します。
内容については、必要に応じてコメントで記載しています。
{
"compilerOptions": {
"sourceMap": true,
"allowJs": true, // JSを許可します
"strict": true, // 型の恩恵を受けるために必須です
"module": "ESNext", // moduleを読み込む際はESNext形式で読み込みます
"target": "es5", // es5の形式にトランスパイルします
"lib": [ // 各種ライブラリを呼び出せます
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"esModuleInterop": true, // モジュールのimport形式のESModules形式とCommonJS形式との互換性のために必須
"baseUrl": "./",
"paths": {
"@/*": "src/*",
},
"include": [
"src",
],
"exclude": [
"node_modules"
],
}
webpackの環境設定
webpack.config.js
の設定を以下に記述します。
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const {
VueLoaderPlugin
} = require('vue-loader')
module.exports = (env = {}) => ({
mode: env.prod ? 'production' : 'development',
devtool: env.prod ? 'source-map' : '',
entry: path.resolve(__dirname, './src/main.ts'),
output: {
path: path.resolve(__dirname, './dist'),
filename: 'bundle.js'
},
devServer: {
contentBase: path.resolve(__dirname, './dist'),
port: 8080,
historyApiFallback: true, // without no routing
},
resolve: {
modules: [path.resolve(__dirname, 'node_modules')],
alias: {
'@': path.resolve(__dirname, './src'),
'vue': '@vue/runtime-dom' // これがないとvue-compilerがVueファイルを認識しません
},
extensions: ['.vue', '.ts', '.tsx']
},
module: {
rules: [
{
test: [/\.vue$/],
loader: 'vue-loader',
},
{
test: /\.sass$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: { hmr: !env.prod }
},
'css-loader',
{
loader: 'sass-loader',
options: {
sassOptions: { indentedSyntax: true }
}
}
]
},
{
test: [/\.ts$/, /\.tsx$/],
use: [
{
loader: 'babel-loader'
},
{
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/] // これがないとTSファイル内でVueファイルを読み込めません
}
}
]
}
],
},
plugins: [
new VueLoaderPlugin(), // VueLoaderPluginがVue3用に必要です
new HtmlWebpackPlugin({
publicPath: 'dist',
filename: 'index.html',
template: 'src/html/index.html',
}),
new MiniCssExtractPlugin({
publicPath: 'dist',
filename: '[name].css',
}),
new webpack.DefinePlugin({
__VUE_OPTIONS_API__: 'true',
__VUE_PROD_DEVTOOLS__: 'false'
})
],
})
注意事項
eslint-plugin-vue
とvue-loader
については、2020/09/30現在ベータ版であるため、今後破壊的変更が加えられる可能性もあります。
おわりに
長々と読んでいただいてありがとうございます。
フロントの環境構築の参考になれば幸いです。
質問や間違いの指摘などありましたら気軽にお願いします!
Discussion