目录

  • 一、原理简介
  • 二、打包过程
    • 1. 创建一个webpack项目
    • 2. 编写组件和打包脚本
    • 3. 打包
  • 三、动态引入
    • 1. 在vue项目中使用
    • 2. 在普通项目中使用
  • 总结

一、原理简介

在使用webpack打包vue项目时,我们一般习惯以项目的main.js为打包入口,构建完整的项目依赖。依赖构建完毕后将打包后的js通过插件html-webapck-plugin引入到HTML模板中,从而实现整个项目的打包。

由于webpack运行于nodejs环境下,只能识别js文件,因此如果遇到其他类型的文件,如.vue,就必须使用对应的loader先转化成js文件。Vue提供了vue-loader来将vue单页面组件转化成js代码(vue-loader本身依赖vue-template-compiler来解析模板,如果组件包含样式,一般还需要引入style-loadercss-loader)。

可能很多人会有一个错觉,是不是webpack只能以js文件为入口?

当然不是这样的!只要有loader的支持,.vue文件同样可以作为打包入口。这也是我们打包单个vue组件的基本思路。下面我们来看具体的打包过程。

二、打包过程

1. 创建一个webpack项目

这个非常简单,首先安装webpack和webpack-cli(高版本webpack依赖webpack-cli):

npm install webpack webpack-cli -g

然后进入要建项目的目录,新建一个文件夹(如vue-pack),打开命令行输入以下指令初始化一个项目:

npm init

一路回车,最终会在该路径下自动生成一个package.json,这是项目描述文件。由于当前项目还没有安装任何依赖,所以package.jsondependencies字段还不存在。所以接下来我们要在当前项目中安装打包单个vue组件所需要的包(高版本的vue-loader需要依赖vue-loader-plugin插件,否则打包的时候会报错):

npm install vue-loader vue-loader-plugin vue-template-compiler vue-style-loader css-loader --save

回车,等待安装完成。现在项目下应该会增加一个node_modules文件夹,这是第三方node包目录。

由于webpack4不再默认生成配置文件,因此我们可以在当前路径下新建一个webpack.config.js文件作为打包的配置文件。

2. 编写组件和打包脚本

由于我们只是简单演示单组件的打包,这里以一个简单的Vue组件为例。我们在当前目录下新建src/HelloWorld.vue,然后编写简单的vue组件:

<template><div>{{ name }}</div>
</template><script>
export default {data() {return {name: 'carter'}}
}
</script><style>div {color: red;}
</style>

现在最关键的是如何配置打包脚本,我们来看webpack.config.js的编写:
webpack.config.js

const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');module.exports = {entry: './src/HelloWorld.vue',output: {path: path.resolve(__dirname, 'dist'),filename: 'helloWorld.js',library: 'helloWorld'},plugins: [new VueLoaderPlugin()],module: {rules: [{//vue 解析test: /\.vue$/,loader: 'vue-loader',},{//css 解析test: /\.css$/,use: ['vue-style-loader', 'css-loader']}]}
}

我们来解释上述配置。

首先,entry字段定义了打包入口为src路径下的HelloWorld.vue,也就是我们将要打包的vue组件。这里的library字段我们在后面会解释。

然后,output定义了打包出口,这里我们会把打包结果输出到当前路径下的dist文件夹,打包结果名为helloWorld.js

随后,我们在plugins中引入了VueLoaderPlugin,这是vue-loader所需的依赖。

最后,我们对不同的资源配置loader。对于.vue后缀的,我们使用vue-loader解析,对于样式,我们使用vue-style-loadercss-loader进行解析。

现在我们来解释一下entry字段的library值的含义。

添加library字段表明这个入口文件打包之后会作为一个第三方库使用,而不是会被插件嵌入到HTML模板。一般来说,文件在打包完成之后不会向外输出变量,而是得到一个立即执行的函数,如:

!(function(){ ... })()

这样的打包结果会被html-template-compiler嵌入到模板中调用:

...
<script src="/js/bundle.js"></script>
...

由于我们的打包入口一般都是main.js,它内部包含new Vue这样的代码,因此由它打包出的js具有自动挂载和初始化的能力,我们只需简单引入它,就可以构建整个vue应用。

但是单vue组件不同,它只是第三方包,没有new Vue这样的语句,不具备自动挂载的能力,需要在引入到项目后手动注册和挂载。因此单vue组件的输出结果必须是一个函数或对象。指定了library字段后,打包结果就变成了:

var helloWorld=function(e){...};

这个函数严格来讲是一个Module对象,它有一个default属性,保存了组件配置。现在你就可以通过变量helloWorld来执行组件的注册和挂载了,这个我们第三部分会介绍。

3. 打包

编写完脚本之后,打包就很容易了。我们去package.json里配置打包脚本:

{..."scripts": {..."build": "webpack",},...
}

现在打开命令行,输入npm run build,你就会发现当前路径下多了一个dist文件夹,里面的helloWorld.js就是我们的打包结果。

三、动态引入

1. 在vue项目中使用

现在假设我们另外有一个项目,需要用到上述组件。而上述打包结果现在已经被保存在当前项目的public文件夹下,我们现在需要在App.vue中动态加载这个js,然后注册和使用组件。如:

public|- js|- helloWorld.js
src|- App.vue|- main.js

App.vue可能会这样写:

<template><div :is="compName"></div>
<template><script>import Vue from 'vue';export default {data() {return {compName: ''}},mounted() {...}}
</script>

我们的目标是在mounted生命周期中挂载这个第三方组件。假设我们还不知道要加载的第三方组件的名字(这里指的其实是打包时的library字段)和路径,我们可能需要先发送一个请求来获取:

mounted () {this.$axios.get('/getLibraryNameAndUrl').then(res => {let compName = res.libraryName;let url = res.url;...})
}

接下来需要动态加载js,并在加载完毕后动态注册它:

mounted () {this.$axios.get('/getLibraryNameAndUrl').then(res => {let compName = res.libraryName;let url = res.url;let script = document.createElement('script');script.src = url;  // '/js/helloWorld.js'script.onload = () => {Vue.component('hello-world', window[compName].default);this.compName = 'hello-world';}document.body.appendChild(script);})
}

现在页面上应该可以渲染出引入的第三方组件了。我们看看这里做了什么。

首先,我们动态创建了一个script标签,并将url设置为第三方helloWorld.js的地址。然后我们注册了script标签的onload事件。我们第二部分已经讲到,helloWorld.js返回的实际上是下面的代码:

var helloWorld= function(e){...};

也就是说,当脚本执行完毕时,window对象上应该会新增一个变量:window.helloWorld。它的值是一个函数,同时它也是一个Module类型的对象。在浏览器输出helloWorld这个变量:

它的default属性就是我们要拿来进行注册组件的对象!我们通过Vue.component动态注册一个名为hello-world的组件(这里也可以选择动态从后台获取,或其他约定好的组件名),传入上述变量的default属性,即可完成注册。

随后我们只需要写this.compName = 'hello-world',template中的div就会被渲染为组件<hello-world></helloWorld>,第三方组件也就渲染完毕。

2. 在普通项目中使用

实际上在普通项目中也是一样的用法。

比如我们有一个普通的HTML页面,它引入了vue的cdn库。如果只是静态引入这个组件,那么可以这样写:

...
<div id="app"></div>
...
<script src="/js/helloWorld.js"></script>
<script>var app = new Vue({el: "#app",components: {helloApp: helloWorld.default},render: h => h('helloApp')})
</script>

如果需要动态加载,那么完全参照vue中的代码,使用document.createElement动态创建脚本标签并进行注册。

总结

实际上上述的打包过程完全可以使用node服务自动化完成,并且可以动态指定组件名,以防止多个组件出现打包冲突。比如我们可以通过nodejs提供的命令行模块:node-cmd,自动执行webpack命令。如果需要指定library字段,可以这样动态拼写:'webpack --output-library' + libraryName

所以你完全可以在服务端构建一个node服务,以单vue组件作为输入,自动执行打包命令,然后输出打包结果,再引入其他项目中。关于这套方案,目前本人仍在实践中…

单个vue组件的打包和动态引入相关推荐

  1. Vue组件库实现按需引入可以这么做

    本文为Varlet组件库源码主题阅读系列第七篇,读完本篇,可以了解到如何通过unplugin-vue-components插件来为你的组件库实现按需引入. 手动引入 前面的文章中我们介绍过Varlet ...

  2. Vue3 父传子、使用 defineAsyncComponent 异步挂载组件、利用 is 动态引入组件

    1.父组件 index.vue defineAsyncComponent 是 Vue3 的异步挂载 <template><div v-for="v in nav_items ...

  3. js 获取vue组件html_vue.js中怎么引入组件?

    前端框架vue,在利用脚手架工具vue-cli创建前端项目时候,怎么引入组件呢?下面本篇文章给大家介绍一下引入子组件的方法.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. vue.j ...

  4. vue组件通信案例练习(包含:父子组件通信及平行组件通信)

    文章目录 一.案例概述 二.代码 准备工作: 案例1.1:父组件向子组件传值(或者叫:子组件使用父组件属性),采用v-bind方式实现 案例1.2:子组件向父组件传值(或者叫:子组件调用父组件方法), ...

  5. vue组件封装技巧,如何对vue模块进行功能封装

    如何对vue模块进行功能封装,vue组件封装技巧 当业务不断累加,导致原本干净整洁的代码越来越冗余,各种变量和注释已经让他人望而却步,往往又苦于重构带来的成本,导致诞生很多巨石应用.与其让自己或他人面 ...

  6. 关于vue 动态引入(异步加载import和require)组件的方法和坑(按需懒加载组件,动态生成路由)babel-plugin-dynamic-import-node 优化编译速度

    前言: 最近在改造vue-cli 2.x + webpack2.x的项目时,由于之前路由是静态的,没有根据菜单权限动态生成前端路由.所以想对此进行改造,然后碰到了一些问题和坑,现在总结一下,避免以后继 ...

  7. vue动态切换css文件_如何在vue组件中动态的引入css文件?

    问题描述 如标签描述的不准确,请见新直能分支调二浏页器朋代说谅 我的需求是开的接都上的和,近很触是没他电同近很触是没发多套皮肤,打包的时候只加载其中某一种的皮肤(不需要动态换肤),因为css文件过大, ...

  8. vue 如何处理两个组件异步问题_Vue动态异步组件实现思路及其问题

    前言:在vue 官方资料中,我们可以可以很学会如何通过vue构建"动态组件"以及"异步组件",然而,在官方资料中,并没有涉及到真正的"动态异步&quo ...

  9. 如何使用vue组件搭建网页并打包发布

    vue组件化项目搭建及编译打包发布 引言 开发环境 开发环境介绍 开发环境安装 使用模板创建项目 编译及打包发布 引言 最近开始学习Vue,Vue 是一个前端框架,特点是数据绑定和组件化.网上很多教程 ...

最新文章

  1. c2 链路_POS链路不能打开的解决办法
  2. cpio备份linux系统,linux cpio 备份命令
  3. 数据库习题(填空题四)
  4. 庖丁解牛之-Android平台RTSP|RTMP播放器设计
  5. [数理统计-逐步回归]国内旅游收入回归
  6. 时不变线性系统和时变线性系统方程的对角化
  7. 首都师范 博弈论 3 4 2反复剔除严格劣策略
  8. 信息学奥赛一本通评测系统P1336
  9. 二进制,十进制,十六进制转化
  10. SQL Server版本和下载地址
  11. 网页回到顶部 GoTop 按钮自动隐藏
  12. JDK 1.4 中打印,
  13. P106双N卡 自动调用方案
  14. eclipse的安装与下载
  15. js验证固定电话、手机号码
  16. 弘辽科技:拼多多关键词出价多少好?出价方法有哪些?
  17. [转载]苹果公司与分工原理
  18. Silverlight概述
  19. mysql数据库导入数据的几种方式
  20. 山寨版tftp服务器

热门文章

  1. linux中tftp服务器设置及测试
  2. abaqus创建路径_Abaqus后处理的四种路径的应用-技术邻社区
  3. 综述论文要写英文摘要吗_关于小论文的一些撰写建议!
  4. numpy 轴与维度的理解
  5. 双下巴的瘦脸运动方法 - 健康程序员,至尚生活!
  6. hadoop操作出现:9000 failed on connection exception: java.net.ConnectException:拒绝访问(已解决)
  7. 尹孝孫 楸溪 門前刺紙欲生毛
  8. 不用深度学习网络,只需预先设置NAS算法,就能实现AutoML自动机器学习的革命吗?
  9. 推荐一款最好用的windows文件管理器
  10. 西门子1200PLC和KTP700触摸屏控制西门子V90伺服电机例子程序