25 Vue源代码的打包
1.介绍
npm install vue@next --save
先安装vue3
在webpack的入口文件main.js里面写入以下代码
import {createApp} from "vue"
const app = createApp({
template:"<h2>{{title}}</h2>",
data(){
return {
title:"i am vue"
}
}
});
app.mount("#app");
运行npm run build, 没有报错
然后打开dist中的index.html,发现并没有显示 i am vue
打开控制台,发现报错
runtime-core.esm-bundler.js:38 [Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".
2. vue版本(runtime-compiler and runtime-only)
如果选择对template进行打包,就需要选择第一种,因为compiler就是对template进行编译的。但是vue默认使用的是版本二:runtime-only, 不包含对template的编译,所以编译不会成功,界面渲染不出来。
render函数就是直接渲染出来虚拟节点v-dom
runtime-compiler
使用
new Vue({
el:"#app",
template: '<App/>',//template替换el里面的内容
components:{App}
})
当我们把template传给Vue实例的时候,它会被保存在Vue实例下面的options,
template被解析(parse)成抽象语法树,ast(abstract syntax tree),
然后第三步,complier,编译成render函数
通过render函数把template翻译成virtual dom,虚拟dom
转换成真实的dom
template(html)->ast->render ->vdom ->真实dom
runtime-only(1.性能更高 2.下面的vue代码量更少)
new Vue({
el:'#app',
render:h => h(App)
})
render ->vdom ->真实dom
new Vue({
el:'#app',
render: function (createElement){
//1. 普通用法:传入标签createElement('标签',{标签的属性},[''])
/* return createElement('h2',
{class:'box'},
['Hello! world!', createElement('button', {class:'mybtn'}, ['按钮'])]) */
//2.传入组件对象:
//return createElement(cpn)
return createElement(App)
//创建出来的标签,替换掉之前的<div id="app"><div>
//那么.vue文件中的template是由谁编译的呢?
//是由vue-template-compier来解析的,将.vue里面的template解析成render函数的,在main.js里面引用的不是整个.vue文件
//引用的是被解析后的App对象,对象里面没有包含任何关于tenplate信息,所有的template已经转成render函数了
}
})
简单总结
如果在之后的开发中,你依然使用template,就需要选择Runtime-Compiler
如果你之后的开发中,使用的是.vue文件夹开发,那么可以选择Runtime-only
3.vue打包后不同版本解析
D:\FrontEnd\07_codershy_Vue3s\webpack_study\code\06_webpack_vue\node_modules\vue\dist文件夹 里面有很多版本的vue。
vue.global.js就是我们cnd引入时候的文件。
如果你不需要编译template,就可以只使用runtime的版本,vue.runtime.global.js
vue.runtime.global.prod.js 是要不要使用生产版本,生成版本是做过压缩的。
-
vue.global.js
包含编译器和运行时的完整版,构建过程中支持动态模板编译 -
vue.runtime.global.js
仅预编译了构建过程中的运行时和必要的模板
第二个是正常src引用的话,就是第一个方式,上面的方式,但是表明了src = .. type="module"的时候使用现在这个。
第三个是在wenpack等构建工具中使用。分两个,一个有complier,一个没有。默认使用的是只有runtime的版本 vue.runtime.esm-bundler.js, 不包含对template的解析,所以没有显示出来。
import {createApp} from 'vue/dist/vue.esm-bundler'
//这样npm run build之后,就会渲染出来
//把main.js总的import换成'vue/dist/vue.esm-bundler' 而不是默认的vue.runtime.esm-bundler.js
vue.runtime.esm-bundler.js
(默认)仅运行时,且要求所有模板必须预编译。这是构建工具的默认入口(通过package.js的module字段),因为当使用构建工具模板时一般都是预编译的(例如:*.vue文件)
vue.esm.bundler.js
:包含运行时编译器。当你使用了构建工具但仍然想编译运行时模板(例如,in-DOM模板或通过javascript字符的内联模板)。你需要在构建工具中配置vue别名到这个文件。
vue.cjs(.prod).js
:
- 服务端使用Nodejs通过require()渲染。
- 如果使用webpack指定
target: 'node'
且正确的使用vue
进行描述,发布时此文件将会载入。
Vue3x基础 - 安装 - 简书 (jianshu.com)
4.全局标识的配置
5.VSCode对SFC文件的支持
6 编写App.vue代码
//main.js
import { sum } from "./js/math";
const { priceFormat } = require("./js/format");
import "./js/element.js"
import {createApp} from 'vue/dist/vue.esm-bundler'
import App from './vue/App.vue'
console.log(sum(20, 30));
console.log(priceFormat());
/* const app = createApp({
template: `<h2>我是vue渲染出来的</h2>`,
data(){
return {
title: "hello world"
}
}
}); */
const app = createApp(App)
app.mount("#app");
template在public的index.html里面,js在main.js里面,这样的话比较麻烦,如果有样式的话,就更麻烦了,三个部分在三个不同的文件里,为了解决这个问题,我们就有了.vue文件,把这三个部分放到一个文件里面。
在src里面创建一个vue文件夹,里面创建一个App.vue文件
App.vue
<template>
<h2>我是Vue渲染出来的</h2>
<h2>{{title}}</h2>
</template>
<script>
export default {
data() {
return {
title: "Hello world",
message:"hahahha"
}
},
methods: {
}
}
</script>
<style>
h2{
color: red;
}
</style>
main.js文件修改为以下
import {createApp} from "vue/dist/vue.esm-bundler"
import App from "./vue/App.vue"
const app = createApp(App )
/*虽然只导出了{
data() {
return {
title: "Hello world",
message:"hahahha"
}
},
methods: {
}
}
这个对象,但是其实会用一个loader对这个vue文件进行编译,它会自动把template里面的东西放到导出的这个对象里面
*/
app.mount("#app");
然后运行npm run build 报错了,原因是无法解析.vue文件
7. App.vue的打包过程
默认情况下vue-loader是对vue2的源代码进行解析的,所以我们要使用vue-loader@next
npm i vue-loader@next -d
然后修改配置文件
{
test:/\.vue$/,
loader:"vue-loader"
}
然后还是会报错,因为vue-loader是依赖@vue/compiler-sfc这个包的,其实对单文件解析的时候是@vue/complier-sfc这个包对他进行解析的。vue2是@vue/vue-template-compiler.
npm i @vue/compiler-sfc -d
8. vue/complier-sfc
如上,对@vue/compiler-sfc 进行配置后,就可以npm run build进行打包。打开index文件。就可以看到我是Vue渲染出来的和Hello world。
9. GlobalFeatureFlags的配置
虽然正确的显示出来了,但是console里面会有一下的报错
runtime-core.esm-bundler.js:3705
Feature flags __VUE_OPTIONS_API__, __VUE_PROD_DEVTOOLS__ are not explicitly defined. You are running the esm-bundler build of Vue, which expects these compile-time feature flags to be globally injected via the bundler config in order to get better tree-shaking in the production bundle.
For more details, see https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags
Starting with 3.0.0-rc.3, esm-bundler
builds now exposes global feature flags that can be overwritten at compile time: 从3.0.0版本开始, esm-bundler
要求我们设置一个global feature 的flag。这里面有两个参数
-
__VUE_OPTIONS_API__
(enable/disable Options API support, default:true
)对vue2做适配,默认是true,就是意味着源代码里面是有一部分代码是对vue-options-api做解析的,
如果代码里面写的都是setup()也就是vue3的代码,我就不需要这部分代码,你就可以设置为false,tree-shaking在打包的时候,发现是false的话,就会把这一部分代码从源代码里面删除掉,体积就会小一些
-
__VUE_PROD_DEVTOOLS__
(enable/disable devtools support in production, default:false
)生产环节下要不要支持devtool,devtool一般是开发阶段使用,生产阶段一般不用它生效,所以设置成false
new DefinePlugin({
BASE_URL : "'./'",
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__:false
}),
警告全部消除了
因为已经使用了vue-loader和vue/complier-sfc对template等等进行处理
然后这时候可以直接使用
import {createApp} from "vue"