間違ってたらご指摘お願いします
参考
- 【2018年】Webpack4でVue.js単一ファイルコンポーネントの作り方 - Qiita
- Getting Started | Vue Loader
- Simple Todo App with Vue
サンプル
サンプルとして簡単なカウンターを作ってみました
【コードはこちら】
bash
yarn init -y
yarn add -D webpack webpack-cli vue vue-loader vue-template-compiler vue-style-loader css-loader babel-loader @babel/core @babel/preset-env
# または、
npm init -y
npm i -D webpack webpack-cli vue vue-loader vue-template-compiler vue-style-loader css-loader babel-loader @babel/core @babel/preset-env
フォルダ構成
.
├ src/
│ ├ components
│ │ └ Btn.vue
│ ├ App.vue
│ └ index.js
├ .babelrc
├ index.html
├ package.json
└ webpack.config.js
webpack.config.js
const VueLoaderPlugin = require("vue-loader/lib/plugin")
module.exports = {
mode: "development",
module: {
rules: [
{
test: /\.vue$/,
loader: "vue-loader",
},
{
test: /\.js$/,
loader: "babel-loader",
},
{
test: /\.css$/,
use: [
"vue-style-loader",
"css-loader",
],
},
]
},
plugins: [
new VueLoaderPlugin()
],
resolve: {
extensions: [".vue", ".js"],
alias: {
"vue$": "vue/dist/vue.esm.js"
}
},
}
.babelrc
{ "presets": ["@babel/preset-env"] }
src/index.js
import Vue from "vue"
import App from "./App"
new Vue({
el: "#app",
template: "<App/>",
components: { App }
})
src/App.vue
<template>
<div id="app" class="container">
<h1>My Counter</h1>
<hr>
<p class="count">{{ count }}</p>
<Btn class="blue" @handleCount="doCount('up')">Up</Btn>
<Btn class="green" @handleCount="doCount('down')">Down</Btn>
</div>
</template>
<script>
import Btn from "./components/Btn"
export default {
components: {
Btn
},
data () {
return {
count: 0,
}
},
methods: {
doCount(countType) {
this.count += (countType === "up" ? 1 : -1)
},
},
}
</script>
<style scope>
.container {
text-align: center;
width: 500px;
}
.count {
font-size: 35px;
margin: 10px;
}
</style>
src/components/Btn.vue
<template>
<button @click="_handleCount">
Count <slot></slot>!
</button>
</template>
<script>
export default {
methods: {
_handleCount() {
this.$emit("handleCount");
}
}
}
</script>
<style scope>
button {
border-radius: 5px;
cursor: pointer;
font-size: 15px;
height: 35px;
width: 40%;
color: #fff;
transition: opacity .15s;
}
button:hover {
opacity: .8;
}
button.blue {
background-color: #007bff;
border-color: #007bff;
}
button.green {
background-color: #28a745;
border-color: #28a745;
}
</style>
index.html
<!DOCTYPE html>
<meta charset=utf-8>
<title>sample</title>
<script src=dist/main.js defer></script>
<div id=app></div>
bash
yarn webpack
#または、
npx webpack
index.html
をブラウザで開くと動きが確認できます
Sassを使う
sass-loader
、node-sass
を追加します
# 全部installする場合
yarn add webpack webpack-cli vue vue-loader vue-template-compiler vue-style-loader css-loader babel-loader @babel/core @babel/preset-env sass-loader node-sass
webpack.config.js
const VueLoaderPlugin = require("vue-loader/lib/plugin")
module.exports = {
mode: "development",
module: {
rules: [
{
test: /\.vue$/,
loader: "vue-loader",
},
{
test: /\.js$/,
loader: "babel-loader",
},
{
- test: /\.css$/,
+ test: /\.scss$/,
use: [
"vue-style-loader",
"css-loader",
+ "sass-loader",
],
},
]
},
plugins: [
new VueLoaderPlugin()
],
resolve: {
extensions: [".vue", ".js"],
alias: {
"vue$": "vue/dist/vue.esm.js"
}
},
}
vue
<style lang="scss" scope>
body {
.container {
text-align: center;
width: 500px;
}
}
/* ... */
</style>
- ソースマップを有効にする
webpack.config.js
const VueLoaderPlugin = require("vue-loader/lib/plugin")
module.exports = {
mode: "development",
module: {
rules: [
{
test: /\.vue$/,
loader: "vue-loader",
},
{
test: /\.js$/,
loader: "babel-loader",
},
{
+ test: /\.scss$/,
use: [
"vue-style-loader",
+ {
+ loader: "css-loader",
+ options: { sourceMap: true },
+ },
+ {
+ loader: "sass-loader",
+ options: { sourceMap: true },
+ },
],
},
]
},
plugins: [
new VueLoaderPlugin()
],
resolve: {
extensions: [".vue", ".js"],
alias: {
"vue$": "vue/dist/vue.esm.js"
}
},
}
source mapが確認できました
PostCSSを使う
postcss-loader
を追加します。今回は例としてpostcss-nested
で試してみます
# 全部installする場合
yarn add webpack webpack-cli vue vue-loader vue-template-compiler vue-style-loader css-loader babel-loader @babel/core @babel/preset-env postcss-loader postcss-nested
webpack.config.js
// ...
{
test: /\.css$/,
use: [
"vue-style-loader",
{
loader: "css-loader",
options: { importLoaders: 1 }
},
{
loader: "postcss-loader",
options: { plugins: [ require("postcss-nested") ] },
},
],
},
// ...
vue
<style scope>
body {
h1 {
color: blue;
}
}
</style>
↑の設定でPostCSSを用いたネスト記法を使ってcssを書けるようになりました、わかりやすくsource mapもつけてみます
webpack.config.js
// ...
{
test: /\.css$/,
use: [
"vue-style-loader",
{
loader: "css-loader",
options: {
sourceMap: true,
importLoaders: 1
},
},
{
loader: "postcss-loader",
options: {
sourceMap: true,
plugins: [ require("postcss-nested") ],
},
},
],
},
// ...
Pugを使う
pug
、pug-plain-loader
を追加します
# 全部installする場合
yarn add webpack webpack-cli vue vue-loader vue-template-compiler vue-style-loader css-loader babel-loader @babel/core @babel/preset-env pug pug-plain-loader
webpack.config.js
// ...
{
test: /\.pug$/,
loader: 'pug-plain-loader'
},
// ...
vue
<template lang="pug">
div
h1 Hello world!
</template>
Hot Reload する
参考:https://vue-loader.vuejs.org/guide/hot-reload.html
webpack-dev-server --hot
とするとうまくいくようです
# 全部installする場合
yarn add webpack webpack-cli webpack-dev-server vue vue-loader vue-template-compiler vue-style-loader css-loader babel-loader @babel/core @babel/preset-env
index.html
<!DOCTYPE html>
<meta charset=utf-8>
<title>sample</title>
<script src=main.js defer></script>
<div id=app></div>
webpack.config.js
const VueLoaderPlugin = require("vue-loader/lib/plugin")
module.exports = {
mode: "development",
module: {
rules: [
{
test: /\.vue$/,
loader: "vue-loader",
},
{
test: /\.js$/,
loader: "babel-loader",
},
{
test: /\.css$/,
use: [
"vue-style-loader",
"css-loader",
],
},
]
},
plugins: [
new VueLoaderPlugin()
],
resolve: {
extensions: [".vue", ".js"],
alias: {
"vue$": "vue/dist/vue.esm.js"
}
},
devServer: {
compress: true,
port: 9000,
open: true
},
}
yarn webpack-dev-server --hot
ページがリロードされることなく、ファイル保存すると、コンポーネントも更新されていることが確認できました。
※--hot
をつけないと、ファイル保存するとページがリロードされるという動きでした。
最後まで読んでいただいてありがとうございました。m(_ _)m