- 创建项目根目录
mdir demo
cd demo
- 创建package.json
npm init -y
- 安装需要的包
npm install --save-dev webpack webpack-cli
npm install --save-dev html-webpack-plugin clean-webpack-plugin webpack-dev-server
npm install --save-dev babel-loader @babel/core
npm install --save-dev vue-loader vue-template-compiler
npm install --save-dev vue-style-loader css-loader
npm install --save-dev webpack-merge
npm install --save vue
- 创建webpack配置文件
其中,webpack.dev.js用于开发环境,webpack.prod.js用于生产环境。
type nul>webpack.common.js
type nul>webpack.dev.js
type nul>webpack.prod.js
//webpack.common.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
const VueLoaderPlugin = require("vue-loader/lib/plugin");
module.exports = {
entry:{
"index":"./src/index.js"
},
output:{
filename:"[name].bundle.js",
path:path.resolve(__dirname,"dist")
},
resolve:{
modules:[path.resolve(__dirname,"node_modules")],
extensions:['.vue','.js','.json']
},
module:{
rules:[
{
test:/\.vue$/,
include:/src/,
exclude:/node_modules/,
loader:'vue-loader'
},
{
test:/\.js$/,
include:/src/,
exclude:/node_modules/,
use:['babel-loader']
},
{
test:/\.css$/,
use:['vue-style-loader','css-loader']
}
]
},
plugins:[
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'index.html')
}),
new CleanWebpackPlugin(),
new VueLoaderPlugin()
],
optimization:{
runtimeChunk:"single",
splitChunks:{
cacheGroups:{
vendor:{
name:"vendor",
priority:1,
chunks:"initial",
test:/[\\/]node_modules[\\/]/,
minChunks:1
},
default:{
name:"common",
chunks:"initial",
minChunks:2
}
}
}
}
}
//webpack.dev.js
const path = require("path");
const {merge} = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common,{
mode:"development",
devtool:"cheap-source-map",
devServer:{
port:3000,
contentBase:path.resolve(__dirname,'dist'),
hot:true
}
})
//webpack.prod.js
const path = require("path");
const {merge} = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common,{
mode:"development"
})
- 修改package.json,添加如下 npm scripts,
"scripts": {
"start": "webpack-dev-server --open --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
}
- 开始编译打包,并启动webpack-dev-server
npm run start
- 打开浏览器,地址栏输入 localhost:3000
ESM版本
- 运行时版本
node_modules\vue\dist\vue.runtime.esm.js,包含 创建Vue实例、渲染、处理虚拟DOM 等代码。
webpack打包时默认使用运行时版本。 - 完整版本
node_modules\vue\dist\vue.esm.js,即 运行时版本+编译器。
编译器,将字符串模板编译成render函数。
显然,运行时版本比完整版本体积小,所以尽量使用运行时版本。
如果应用中需要编译字符串模板,则使用完整版本,在webpack配置文件中添加如下配置:
module.exports = {
resolve:{
alias:{
"vue$":"vue/dist/vue.esm.js"
}
}
}
单文件组件
单文件组件,就是一个.vue
文件,描述了一个独立组件,包含3个语言块。
- 模板,
<template></template>
<template></template>
里只能包含一个根节点 - 脚本,
<script></script>
- 样式,
<style></style>
当然,也可以自定义 语言块,如<custom></custom>
//helloworld.vue
<template>
</template>
<script>
</script>
<style>
</style>
<custom>
</custom>
vue-loader
vue-loader会解析、提取 单文件组件中的<template>
、<script>
和<style>
,并将它们分别交给对应的loader,如babel-loader
、css-loader
处理。
- 问题
vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config. - 解决方法
没有引入插件VueLoaderPlugin
导致。
使用vue-loader时,VueLoaderPlugin
不可缺少。
const VueLoaderPlugin = require("vue-loader/lib/plugin");
module.exports = {
plugins:[
new VueLoaderPlugin()
]
}
简单示例
//index.js
import Vue from "vue";
import App from "./components/app.vue";
const vm = new Vue({
render:createElement => createElement(App)
}).$mount('#root');
//app.vue
<template>
<div>
<AnchoredHeading v-bind:level="1">hello</AnchoredHeading>
<AnchoredHeading v-bind:level="2">world</AnchoredHeading>
<AnchoredHeading v-bind:level="3">have</AnchoredHeading>
<AnchoredHeading v-bind:level="4">a</AnchoredHeading>
<AnchoredHeading v-bind:level="5">nice</AnchoredHeading>
<AnchoredHeading v-bind:level="6">day</AnchoredHeading>
</div>
</template>
<script>
import AnchoredHeading from "./anchoredHeading.vue";
export default {
components:{
AnchoredHeading
}
}
</script>
//anchoredHeading.vue
<template>
<div>
<h1 v-if="level===1">
<slot></slot>
</h1>
<h2 v-if="level===2">
<slot></slot>
</h2>
<h3 v-if="level===3">
<slot></slot>
</h3>
<h4 v-if="level===4">
<slot></slot>
</h4>
<h5 v-if="level===5">
<slot></slot>
</h5>
<h6 v-if="level===6">
<slot></slot>
</h6>
</div>
</template>
<script>
export default {
props:{
level:{
type:Number,
required:true
}
}
}
</script>