1.Vue封装组件并发布到npm仓库
2.一文带你快速上手Rollup
3.Vue3源码架构简析及Monorepo流程构建
4.10分钟快速精通rollup.js——Vue.js源码打包原理深度分析
5.封装Vue组件库的码打方法
Vue封装组件并发布到npm仓库
使用Vue框架进行开发时,组件封装是码打一个非常常规的操作。封装好的码打组件可以在项目的任意地方使用,甚至可以直接从npm仓库下载别人封装好的码打组件进行使用,比如iview、码打element-ui等组件库。码打市场状态指标源码然而,码打每个公司的码打业务场景可能不同,开发人员仍需要封装自己的码打组件。如果换了新项目,码打只能复制组件代码到新项目中,码打这样略显繁琐。码打其实可以将组件上传到npm仓库,码打需要时可以直接从npm安装使用。码打 封装Vue组件的码打好处主要有两点:环境准备
由于此次封装的是Vue组件,因此直接在Vue脚手架项目中进行封装即可。初始化Vue项目
运行项目
组件封装
步骤1:新建package文件夹在src下面新建一个package文件夹,存放所有需要上传的组件。
打算封装两个组件:pig-button、pig-input,分别在package文件夹下新建存放两个组件代码的文件夹。
步骤2:编写组件代码以pig-button组件为例,编写代码,然后引用到App.vue组件验证组件可用性。
最终效果显示组件可用。
步骤3:使用Vue插件模式封装组件的关键步骤,使用Vue提供的install方法,使得插件在使用Vue.use(plugin)时被调用,实现全局注册。
在package目录下新建index.js文件,配置组件的全局注册。
组件打包
完成组件封装后,需要进行打包。
修改package.json文件,配置打包命令。
执行打包命令,生成打包后的文件。
发布到npm
初始化package.json文件。
注册npm账号,有源码怎么假设切换npm源。
添加npm用户。
在pig-ui目录下执行发布npm命令。
发布成功后,可在npm官网查看发布的npm包。
从npm安装使用
执行安装命令。
在main.js中引用注册。
修改App.vue文件,直接使用组件。
总结起来,Vue组件封装发布到npm仓库的整体难度不大,关键在于理解Vue的install方法以及打包相关知识。最重要的是如何封装一个适用范围广、扩展性高的公用组件。此项目源码已公开。一文带你快速上手Rollup
项目中一直用的都是webpack,前一段需要开发几个类库供其他平台使用,本来打算继续用webpack的,但感觉webpack用来开发js库,不仅繁琐而且打包后的文件体积也比较大。正好之前看vue源码,知道vue也是通过rollup打包的。这次又是开发类库的,于是就快速上手了rollup。
什么是rollup?
关于rollup的介绍,官方文档已经写的很清楚了:Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。
与Webpack偏向于应用打包的定位不同,rollup.js更专注于Javascript类库打包。
我们熟知的Vue、React等诸多知名框架或类库都是通过rollup.js进行打包的。
为什么是rollup?
webpack我相信做前端的同学大家都用过,那么为什么有些场景还要使用rollup呢?这里我简单对webpack和rollup做一个比较:
总体来说webpack和rollup在不同场景下,都能发挥自身优势作用。webpack对于代码分割和静态资源导入有着“先天优势”,并且支持热模块替换(HMR),而rollup并不支持。
所以当开发应用时可以优先选择webpack,等量k线源码但是rollup对于代码的Tree-shaking和ES6模块有着算法优势上的支持,若你项目只需要打包出一个简单的bundle包,并是基于ES6模块开发的,可以考虑使用rollup。
其实webpack从2.0开始就已经支持Tree-shaking,并在使用babel-loader的情况下还可以支持es6 module的打包。实际上,rollup已经在渐渐地失去了当初的优势了。但是它并没有被抛弃,反而因其简单的API、使用方式被许多库开发者青睐,如React、Vue等,都是使用rollup作为构建工具的。
快速上手
我们先花大概十分钟左右的时间来了解下rollup的基本使用以及完成一个hello world。
安装
首先全局安装rollup:
接着,我们初始化一个如下所示的项目目录
首先我们在src/index.js中写入如下代码:
然后在命令行执行以下命令:
执行命令,我们即可在dist目录下生成bundle.js文件:
这时,我们再在example/index.html中引入上面打包生成的bundle.js文件,打开浏览器:
如我们所预料的,控制台输出了柯森。
到这里,我们就用rollup打包了一个最最简单的demo。
可能很多同学看到这里对于上面命令行中的参数不是很明白,我依次说明下:
其实除了这两个,还有很多其他常用的命令(这里我暂且列举剩下两个也比较常用的,完整的 rollup 命令行参数):
使用配置文件(rollup.config.js)
使用命令行的方式,如果选项少没什么问题,但是如果添加更多的选项,这种命令行的方式就显得麻烦了。
为此,我们可以创建配置文件来囊括所需的选项
在项目中创建一个名为rollup.config.js的文件,增加如下代码:
然后命令行执行:
打开dist/bundle.js文件,我们会发现和上面采用命令行的方式打包出来的结果是一样的。
这里,我对配置文件的选项做下简单的说明:
到这里,相信你已经差不多上手rollup了。
进阶
但是网站被入侵源码,这对于真实的业务场景是远远不够的。
下面,我将介绍rollup中的几种常用的插件以及external属性、tree-shaking机制。
resolve插件
为什么要使用resolve插件
在上面的入门案例中,我们打包的对象是本地的js代码和库,但实际开发中,不太可能所有的库都位于本地,我们大多会通过npm下载远程的库。
与webpack和browserify这样的其他捆绑包不同,rollup不知道如何打破常规去处理这些依赖。因此我们需要添加一些配置。
resolve插件使用
首先在我们的项目中添加一个依赖the-answer,然后修改src/index.js文件:
执行npm run build。
这里为了方便,我将原本的rollup -c -w添加到了package.json的scripts中:"build": "rollup -c -w"
会得到以下报错:
打包后的bundle.js仍然会在Node.js中工作,但是the-answer不包含在包中。为了解决这个问题,将我们编写的源码与依赖的第三方库进行合并,rollup.js为我们提供了resolve插件。
首先,安装resolve插件:
修改配置文件rollup.config.js:
这时再次执行npm run build,可以发现报错已经没有了:
打开dist/bundle.js文件:
打包文件bundle.js中已经包含了引用的模块。
有些场景下,虽然我们使用了resolve插件,但可能我们仍然想要某些库保持外部引用状态,这时我们就需要使用external属性,来告诉rollup.js哪些是外部的类库。
external 属性
修改rollup.js的配置文件:
重新打包,打开dist/bundle.js文件:
这时我们看到the-answer已经是做为外部库被引入了。
commonjs插件
为什么需要commonjs插件
rollup.js编译源码中的模块引用默认只支持 ES6+的模块方式import/export。然而大量的npm模块是基于CommonJS模块方式,这就导致了大量 npm模块不能直接编译使用。
因此使得rollup.js编译支持npm模块和CommonJS模块方式的插件就应运而生:@rollup/plugin-commonjs。
commonjs插件使用
首先,安装该模块:
然后修改rollup.config.js文件:
babel插件
为什么需要babel插件?
我们在src目录下添加es6.js文件(⚠️ 这里我们使用了 es6 中的箭头函数):
然后修改rollup.config.js配置文件:
执行打包,可以看到dist/esBundle.js文件内容如下:
可以看到箭头函数被保留下来,这样的jdk 在线 源码下载代码在不支持ES6的环境下将无法运行。我们期望在rollup.js打包的过程中就能使用babel完成代码转换,因此我们需要babel插件。
babel插件的使用
首先,安装:
同样修改配置文件rollup.config.js:
然后打包,发现会出现报错:
提示我们缺少@babel/core,因为@babel/core是babel的核心。我们来进行安装:
再次执行打包,发现这次没有报错了,但是我们尝试打开dist/esBundle.js:
可以发现箭头函数仍然存在,显然这是不正确的,说明我们的babel插件没有起到作用。这是为什么呢?
原因是由于我们缺少.babelrc文件,添加该文件:
我们看.babelrc配置了preset env,所以先安装这个插件:
这次再次执行打包,我们打开dist/esBundle.js文件:
可以看到箭头函数被转换为了function,说明babel插件正常工作。
json插件
为什么要使用json插件?
在src目录下创建json.js文件:
内容很简单,就是引入package.json,然后去打印author字段。
修改rollup.config.js配置文件:
执行打包,发现会发生如下报错:
提示我们缺少@rollup/plugin-json插件来支持json文件。
json插件的使用
来安装该插件:
同样修改下配置文件,将插件加入plugins数组即可。
然后再次打包,发现打包成功了,我们打开生成的dist/jsonBundle目录:
完美!!
tree-shaking机制
这里我们以最开始的src/index.js为例进行说明:
修改上述文件:
执行打包。打开dist/bundle.js文件:
再次修改src/index.js文件:
再次执行打包,打开打包文件:
发现了什么?
我们发现关于变量b的定义没有了,因为源码中并没有用到这个变量。这就是ES模块著名的tree-shaking机制,它动态地清除没有被使用过的代码,使得代码更加精简,从而可以使得我们的类库获得更快的加载速度。
总结
本文大致向大家介绍了什么是rollup以及如何快速上手rollup。文中提到的这些其实只是冰山一角,rollup能玩的东西还有很多,关于更多可以去 rollup 官网查询。
Vue3源码架构简析及Monorepo流程构建
Vue3通过Monorepo方式管理代码,核心在于packages文件夹,存放功能独立的依赖。
Monorepo,即单代码库管理方式,一个仓库中管理多个模块/包,简化依赖和代码共享,尤其适合大型项目。
选择Monorepo模式,能提高开发效率和代码复用性,简化仓库管理。
建立Vue3项目结构,首先构建依赖管理的packages文件夹,分别开发reactivity和shared两个模块,并初始化仓库。
在根目录的package.json文件中,对工作空间进行改造,更改子包名称。
安装依赖时,通过快捷方式安装shared和reactivity,便于全局引入使用(子包以@vue开头,集中存放)。
开发项目使用typescript和rollup打包,根目录下的package.json中安装相关依赖。
在workspace模式下安装依赖,需额外添加-W参数。
依赖安装相关说明:创建tsconfig.json配置文件,进行workspace配置和目录结构配置,指定模块名称及打包选项。
分钟快速精通rollup.js——Vue.js源码打包原理深度分析
Vue.js源码打包基于rollup.js的API,流程大致可分为五步。首先将Vue.js源码clone到本地,安装依赖,然后通过build指令进行打包。打包成功后会在dist目录下创建打包文件。Vue.js还提供了另外两种打包方式:“build:ssr"和"build:weex”。
Vue.js打包源码分析,Vue.js源码打包基于rollup.js的API,流程大致可分为五步,如下图所示:执行npm run build时,会从scripts/build.js开始执行。前5行分别导入了5个模块,这5个模块的用途在前置学习教程中已经详细过。第7行通过同步方法判断dist目录是否存在,如果不存在则通过同步方法创建dist目录。生成rollup配置,生成dist目录后,通过以下代码生成了rollup的配置文件。代码虽然只有短短一句,但是做了很多事情。首先它加载了scripts/config.js模块,然后调用其中的getAllBuilds()方法。接下来导入了scripts/alias.js模块,alias.js模块输出了一个对象,这个对象中定义了所有的别名及其对应的绝对路径。这个模块中定义了resolve()方法,用于生成绝对路径。
Vue.js打包流程分析,Vue.js源码打包基于rollup.js的API,流程大致可分为五步,如下图所示:执行npm run build时,会从scripts/build.js开始执行。前5行分别导入了5个模块,这5个模块的用途在前置学习教程中已经详细过。第7行通过同步方法判断dist目录是否存在,如果不存在则通过同步方法创建dist目录。生成rollup配置,生成dist目录后,通过以下代码生成了rollup的配置文件。代码虽然只有短短一句,但是做了很多事情。首先它加载了scripts/config.js模块,然后调用其中的getAllBuilds()方法。接下来导入了scripts/alias.js模块,alias.js模块输出了一个对象,这个对象中定义了所有的别名及其对应的绝对路径。这个模块中定义了resolve()方法,用于生成绝对路径。
Vue.js打包流程分析,Vue.js源码打包基于rollup.js的API,流程大致可分为五步,如下图所示:执行npm run build时,会从scripts/build.js开始执行。前5行分别导入了5个模块,这5个模块的用途在前置学习教程中已经详细过。第7行通过同步方法判断dist目录是否存在,如果不存在则通过同步方法创建dist目录。生成rollup配置,生成dist目录后,通过以下代码生成了rollup的配置文件。代码虽然只有短短一句,但是做了很多事情。首先它加载了scripts/config.js模块,然后调用其中的getAllBuilds()方法。接下来导入了scripts/alias.js模块,alias.js模块输出了一个对象,这个对象中定义了所有的别名及其对应的绝对路径。这个模块中定义了resolve()方法,用于生成绝对路径。
Vue.js打包流程分析,Vue.js源码打包基于rollup.js的API,流程大致可分为五步,如下图所示:执行npm run build时,会从scripts/build.js开始执行。前5行分别导入了5个模块,这5个模块的用途在前置学习教程中已经详细过。第7行通过同步方法判断dist目录是否存在,如果不存在则通过同步方法创建dist目录。生成rollup配置,生成dist目录后,通过以下代码生成了rollup的配置文件。代码虽然只有短短一句,但是做了很多事情。首先它加载了scripts/config.js模块,然后调用其中的getAllBuilds()方法。接下来导入了scripts/alias.js模块,alias.js模块输出了一个对象,这个对象中定义了所有的别名及其对应的绝对路径。这个模块中定义了resolve()方法,用于生成绝对路径。
Vue.js打包流程分析,Vue.js源码打包基于rollup.js的API,流程大致可分为五步,如下图所示:执行npm run build时,会从scripts/build.js开始执行。前5行分别导入了5个模块,这5个模块的用途在前置学习教程中已经详细过。第7行通过同步方法判断dist目录是否存在,如果不存在则通过同步方法创建dist目录。生成rollup配置,生成dist目录后,通过以下代码生成了rollup的配置文件。代码虽然只有短短一句,但是做了很多事情。首先它加载了scripts/config.js模块,然后调用其中的getAllBuilds()方法。接下来导入了scripts/alias.js模块,alias.js模块输出了一个对象,这个对象中定义了所有的别名及其对应的绝对路径。这个模块中定义了resolve()方法,用于生成绝对路径。
Vue.js打包流程分析,Vue.js源码打包基于rollup.js的API,流程大致可分为五步,如下图所示:执行npm run build时,会从scripts/build.js开始执行。前5行分别导入了5个模块,这5个模块的用途在前置学习教程中已经详细过。第7行通过同步方法判断dist目录是否存在,如果不存在则通过同步方法创建dist目录。生成rollup配置,生成dist目录后,通过以下代码生成了rollup的配置文件。代码虽然只有短短一句,但是做了很多事情。首先它加载了scripts/config.js模块,然后调用其中的getAllBuilds()方法。接下来导入了scripts/alias.js模块,alias.js模块输出了一个对象,这个对象中定义了所有的别名及其对应的绝对路径。这个模块中定义了resolve()方法,用于生成绝对路径。
封装Vue组件库的方法
封装组件库让我们在之后的工作中可以复用现成的代码,同时保持了组件的稳定性。本文简要概述了封装Vue组件库的2种方法:vue-cli、webpack。
vue-clivue-cli自带编译为库的功能。
命令编写好源码后,执行命令:
vue-cli-servicebuild--targetlib--nameindex--destdist./src/lib/index.ts--name参数设置库的名字,--dest参数设置生成文件的保存目录,./src/lib/index.ts表示入口文件。
参考资料vue-cli-servicebuild。
输出这个命令在dist目录中生成了CJS和UMD的文件,同时CSS也被处理出称为一个单独的文件。
依赖vue-cli没有配置好组件库的外部依赖,我们需要在vue.config.js中设置。
constPackageJson=require('./package.json')module.exports={ configureWebpack:{ externals:Object.keys(PackageJson.dependencies)}}webpackWebpack打包组件库的方式与打包应用方式类似,除了我们需要设置library属性。示例:
constPackageJson=require('./package.json')constPath=require('path')const{ VueLoaderPlugin}=require('vue-loader')const{ CleanWebpackPlugin}=require('clean-webpack-plugin')module.exports={ mode:'production',entry:Path.resolve(__dirname,'./src/index.ts'),output:{ path:Path.resolve(__dirname,'dist'),filename:'index.js',library:{ type:'commonjs'}},externals:Object.keys(PackageJson.dependencies),resolve:{ extensions:['.js','.json','.vue','.ts','.scss'],alias:{ vue:'vue/dist/vue.esm-bundler.js'}},module:{ rules:[{ test:/\.vue$/,loader:'vue-loader'},{ test:/\.(t|j)s$/,loader:'babel-loader',exclude:/node_modules/},{ test:/\.scss$/,use:['style-loader','css-loader','sass-loader']}]},plugins:[newVueLoaderPlugin(),newCleanWebpackPlugin()],devtool:'source-map'}output.library.type属性用于配置生成的目标模块类型。