vue-cli3插件初体验 - 蓝蓝设计_UI设计公司

帝皇彩票官网

追求卓越一诺千金

蓝蓝设计,2011年成立,主创清华团队,专注软件和互联网ui设计开发。擅长企业信息化管理、监控、大数据软件UIUE咨询和设计开发服务。立足UI,好好学习,天天进步!


vue-cli3插件初体验

2019-9-5 释然 前端及开发文章及欣赏


vue-cli3发布自2018年8月,距离现在还不是特别久,最好搭建项目刚好用到,所以写下这篇文章,记录一下踩坑经历。

vue的作者说过,vue-cli的本质是模

版的拉取,太多的配置导致了模版的难以维护,所以重构后的版本提供了插件的功能,一个插件对应一个功能,这样避免了多个模版,也使得cli维护性得到提高,这也是本篇文章的核心介绍内容。

帝皇彩票官网 我对cli3的理解是,一方面扩展了cli2的核心能力 ,一方面封装了webpack逻辑和配置。在过去要去做一个cli,通常需要阅读cli2的代码,cli2的核心模块分别是 generator,prompts,template,git-repo,并用同样的方法去做一个cli,这样其实成本不小,cli3的插件就是提供了这样一种能力,你用他的规则,去做一个npm包,并发到仓库,就可以获得这种能力。

首先,先介绍一下vue-cli3,他的发布带了哪些新功能呢?我总结一下,大概有以下5点:

1.功能丰富。这点相信大家都很好理解,他实在太好用了,模版里包含了大多数业界比较新的功能,可以一键集成typescripts等类型定义工具, eslint/tslint等语法检验工具,风格规范,prettier,husky等格式化工具,还有postcss、pwa、vue-cli-server等等。

2.提高封装性和扩展性。这点指的是vue-cli-server,在过去webpack的逻辑和配置在项目里独立维护,各个项目之间就像孤岛,vue-cli-server就像一个纽带,连接起了各个项目,为项目升级webpack提供便利性,并且通过一份配置,提供个性化配置。

这里顺带扯一下vue。config。js, 这个东西就是用来个性化配置webpack的,他提供了很多的配置项,具体可以看官方文档:

帝皇彩票官网 https://cli.vuejs.org/zh/config/

我们挑几个常用的来讲:

configureWebpack,这个几乎是用的比较多的,简单的方法,可以通过配置的方式配置,如下所示:

 
	
  1. module.exports = {
  2. configureWebpack: {
  3. plugins: [
  4. new MyAwesomeWebpackPlugin()
  5. ]
  6. }
  7. }复制代码


帝皇彩票官网 这份配置,最终会被合并到原来的配置里,不会覆盖。

复杂的方法,可以往这个字段传一个函数,如下所示:

 
  1. module.exports = {
  2. configureWebpack: config => {
  3. if (process.env.NODE_ENV === 'production') {
  4. // 为生产环境修改配置...
  5. } else {
  6. // 为开发环境修改配置...
  7. }
  8. }
  9. }复制代码

这样就可以在一个函数里做一些简单的逻辑,config是webpack config,你可以直接修改config对象,也可以返回一个对象,这个对象最终也会被合并会webpack对象。

第三种方式,是通过webpack-chain来链式调用,代码如下所示:

 
  1. module.exports = {
  2. chainWebpack: config => {
  3. config.module
  4. .rule('vue')
  5. .use('vue-loader')
  6. .loader('vue-loader')
  7. .tap(options => {
  8. // 修改它的选项...
  9. return options
  10. })
  11. }
  12. }复制代码

3.提供图形化管理界面,最所周知,gui易懂,cli高效,vue在降低学习门槛这方面,已经是非常好了。

帝皇彩票官网 通过vue ui指令,可以查看编译各个模块的情况,模块依赖情况,插件的情况,非常便于管理。

4.便捷性。vue-cli-server不仅支持项目的编译,也支持单文件的编译,具体的方法可以看官网介绍。

5.提供了cli的核心能力,也就是问询,模版渲染,文件生成这几大核心功能。具体的示意图可以看如下:


以上是cli2的核心模块,需要引用hbs,inquirer.js,metalsmit等基本模块,cli3的插件机制基本帮我们封装好了,我们只需要根据插件的规范,就可以获取这种能力。

由于有的读者可能对cli2的流程比较陌生,所以我想简单描述一下cli2的工作流程,如下图所示:


首先,cli2提供init指令,执行这个指令,会去远程拿模版文件,并拉到本地用户目录的.vue-template的文件夹,然后通过meta里问题,去问你,然后生成最终模版到你执行命令的目录。

说完vue-cli2,我们来看看vue-cli3的插件是怎么样的?

首先根据插件的位置,我们分成了cli插件,和service插件。cli的插件有完整的开发目录,所能做的事情也比较多一点,service插件是一份js文件,导出一个函数。

cli插件的目录如下所示:


具体的用发可以在官网了解到:

https://cli。vuejs。org/zh/dev-guide/plugin-dev。html#cli-%E6%8F%92%E4%BB%B6

那么他们是怎么工作的呢?

cli的代码主要在@vue/cli 下面,他的大概的流程如下图所示:


@vue/cli/bin/vue。js:

 
  1. program
  2. .command('add <plugin> [pluginOptions]')
  3. .description('install a plugin and invoke its generator in an already created project')
  4. .option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
  5. .allowUnknownOption()
  6. .action((plugin) => {
  7. require('../lib/add')(plugin, minimist(process.argv.slice(3)))
  8. })
  9. program
  10. .command('invoke <plugin> [pluginOptions]')
  11. .description('invoke the generator of a plugin in an already created project')
  12. .option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
  13. .allowUnknownOption()
  14. .action((plugin) => {
  15. require('../lib/invoke')(plugin, minimist(process.argv.slice(3)))
  16. })复制代码

首先,执行vue指令,会执行@vue/cli/bin/vue.js,这里定义了vue add , vue invoke,vue build,vue serve,等指令,可以看出,add指令其实是包含invoke指令的,add指令主要是安装一个包,并且触发generator.js,invoke主要是触发generator.js。

然后再来看@vue/cli/lib/add。js,

 
  1. const packageManager = loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : 'npm')
  2. await installPackage(context, packageManager, options.registry, packageName)复制代码
 
  1. const generatorPath = resolveModule(`${packageName}/generator`, context)
  2. if (generatorPath) {
  3. invoke(pluginName, options, context)
  4. } else {
  5. log(`Plugin ${packageName} does not have a generator to invoke`)
  6. }复制代码

add.js主要安装包,然后执行invoke模块,我们再看看invoke模块做了什么。

@vue/cli/lib/invoke.js

 
	
  1. const generator = new Generator(context, {
  2. pkg,
  3. plugins: [plugin],
  4. files: await readFiles(context),
  5. completeCbs: createCompleteCbs,
  6. invoking: true
  7. })复制代码

invoke里主要实例化generator类,然后把你的插件当成参数传给类,generator类算是vue-cli的核心类了。

@vue/cli/lib/generator。js

 
  1. plugins.forEach(({ id, apply, options }) => {
  2. const api = new GeneratorAPI(id, this, options, rootOptions)
  3. apply(api, options, rootOptions, invoking)
  4. })复制代码

这个类主要负责执行你的插件,然后把generatorapi作为参数传入插件的generator.js导出的函数。

具体的vue-cli插件的开发是怎么样的呢,我写了一个demo,用在模拟多项目的ci模版管理,通常每个项目都有一份.gitlab-ci.yml模版,所以我们一般可以抽出一个公共的ci模版来管理,这里我用cli插件来管理,真正的项目可能不具备可行性,这里我只是用来写一个例子。



目录结构大概如上所示,执行vue add foo后,就会出现propmts对话框,然后选择答案后,就会根据配置生成模版到你的根目录下。


_gitlab-ci。yml ,根据问题选择是否用私有npm仓库:

 
  1. script:
  2. <%_ if (options.config === 'npm') { _%>
  3. - nrm add companynpm http://xxx.y.cn:XXXXX/
  4. - nrm use companynpm
  5. <%_ } _%>复制代码

prompts。js,主要一些问题的设计:

 
  1. module.exports = [
  2. {
  3. name: 'config',
  4. type: 'list',
  5. message: `是否需要切换内部源:`,
  6. choices: [
  7. {
  8. name: '需要',
  9. value: 'npm',
  10. short: ''
  11. },
  12. {
  13. name: '不需要',
  14. value: 'npm',
  15. short: ''
  16. }
  17. ]
  18. }
  19. ]复制代码

generator.js 这个模块很简单,直接渲染模版

 
  1. module.exports = (api, options, rootOptions) => {
  2. // 复制并用 ejs 渲染 `./template` 内所有的文件
  3. api.render('。/template')
  4. }复制代码

service插件主要放在项目本地,是一份js代码,然后导出一个函数,通过package.json配置指向这个js文件的路径,


service主要依赖的代码在@vue/cli-service里,首先先执行@vue/cli-service/bin/vue-cli-service。js文件,


 
  1. const Service = require('../lib/Service')
  2. const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
  3. .....
  4. service.run(command, args, rawArgv).catch(err => {
  5. error(err)
  6. process.exit(1)
  7. })复制代码

该文件实例化Service类,这个类是service插件的核心类,然后再执行run方法。

再来看看@vue/cli-service/lib/Service.js的代码:

首先构造函数执行resolvePlugin,把官方提供的插件和项目里的插件都加载进来,

 
  1. constructor (context, { plugins, pkg, inlineOptions, useBuiltIn } = {}) {
  2. this.plugins = this.resolvePlugins(plugins, useBuiltIn)
  3. }复制代码

resolvePlugin这个函数主要在这里引入本地的插件:

 
  1. resolvePlugins (inlinePlugins, useBuiltIn) {
  2. // Local plugins
  3. if (this.pkg.vuePlugins && this.pkg.vuePlugins.service) {
  4. const files = this.pkg.vuePlugins.service
  5. if (!Array.isArray(files)) {
  6. throw new Error(`Invalid type for option 'vuePlugins.service', expected 'array' but got ${typeof files}.`)
  7. }
  8. plugins = plugins.concat(files.map(file => ({
  9. id: `local:${file}`,
  10. apply: loadModule(file, this.pkgContext)
  11. })))
  12. }
  13. return plugins
  14. }复制代码

run方法又会执行init方法,在该方法内部执行插件:

 
  1. init (mode = process.env.VUE_CLI_MODE) {
  2. // apply plugins.
  3. this.plugins.forEach(({ id, apply }) => {
  4. apply(new PluginAPI(id, this), this.projectOptions)
  5. }
  6. }复制代码


那么service插件要如何来实践,我们来看如下的例子:

首先在package。json配置一下,指向本地的插件my-service。js

 
  1. "vuePlugins": {
  2. "service": [
  3. "my-service.js"
  4. ]
  5. }复制代码

帝皇彩票官网 my-service。js的代码如下所示:

 
  1. const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
  2. const webpack = require('webpack');
  3. module.exports = (api, projectOptions) => {
  4. api.registerCommand(
  5. 'analyze',
  6. {
  7. description: 'start analyze server',
  8. },
  9. (args) => {
  10. // 注册 `vue-cli-service analyze`
  11. let options = projectOptions.pluginOptions.demoOptions
  12. console.log(options);
  13. // resolve webpack config
  14. const webpackConfig = api.resolveWebpackConfig();
  15. webpackConfig.plugins.push(new BundleAnalyzerPlugin());
  16. webpack(webpackConfig,(err,stats)=>{
  17. if(!err) console.log('打包成功')
  18. })
  19. },
  20. );
  21. };复制代码

该插件主要扩展vue-cli-service的指令,加了analyze指令,这个指令主要会向webpack的配置增加一个BundleAnalyzerPlugin的插件,用来分析包的大小,当然,这里也是没有太大的现实可行性的,vue-cli 提供了vue ui的Gui界面让你看到打包后各个模块的大小,或者cli的命令,vue-cli-service build --report,也能生一个报告,效果也是一样。


至此,vue-cli和service插件的使用和实现都介绍完了,如果有哪里写的不到位,希望各位大神能提出指正

标签: vue-cli3插件初体验 « 全球都在用的Booking,是如何做设计改版升级的? | 图解WWDC 设计分会:映射与可供性»


蓝蓝 http://www.bjhbys.com

  1. 2019年11月(11)
  2. 帝皇彩票官网2019年10月(53)
  3. 2019年9月(48)
  4. 2019年8月(63)
  5. 2019年7月(59)
  6. 2019年6月(59)
  7. 2019年5月(31)
  8. 2019年4月(37)
  9. 2019年3月(43)
  10. 2019年2月(26)
  11. 2019年1月(45)
  12. 2018年12月(41)
  13. 2018年11月(40)
  14. 帝皇彩票官网2018年10月(29)
  15. 2018年9月(40)
  16. 2018年8月(87)
  17. 2018年7月(107)
  18. 2018年6月(86)
  19. 2018年5月(110)
  20. 2018年4月(40)
  21. 2018年3月(35)
  22. 2017年8月(35)
  23. 2017年7月(45)
  24. 2017年6月(7)
  25. 帝皇彩票官网2017年5月(27)
  26. 2017年4月(51)
  27. 帝皇彩票官网2017年3月(70)
  28. 2017年2月(65)
  29. 帝皇彩票官网2017年1月(69)
  30. 2016年12月(55)
  31. 2016年11月(111)
  32. 2016年10月(92)
  33. 2016年9月(53)
  34. 2016年8月(9)
  35. 2016年7月(4)
  36. 2016年6月(9)
  37. 2016年3月(19)
  38. 2016年2月(26)
  39. 2016年1月(30)
  40. 2015年12月(33)
  41. 2015年11月(35)
  42. 2015年10月(46)
  43. 2015年9月(43)
  44. 2015年8月(40)
  45. 2015年7月(33)
  46. 2015年6月(46)
  47. 2015年5月(58)
  48. 2015年4月(70)
  49. 2015年3月(55)
  50. 2015年2月(17)
  51. 帝皇彩票官网2015年1月(33)
  52. 2014年12月(21)
  53. 2014年11月(84)
  54. 2014年10月(94)
  55. 2014年9月(6)
  56. 2014年8月(1)
  57. 2014年7月(13)
  58. 2014年6月(66)
  59. 帝皇彩票官网2014年5月(99)
  60. 2014年4月(88)
  61. 2014年3月(102)
  62. 2014年2月(68)
  63. 2014年1月(83)
  64. 2013年12月(106)
  65. 2013年11月(112)
  66. 2013年10月(61)
  67. 2013年9月(20)
  68. 2013年7月(13)
  69. 2013年6月(27)
  70. 2013年5月(48)
  71. 2013年4月(39)
  72. 2013年3月(8)
  73. 2013年2月(20)
  74. 2013年1月(31)
  75. 2012年12月(33)
  76. 2012年11月(31)
  77. 2012年10月(23)
  78. 2012年9月(8)
  79. 帝皇彩票官网2012年7月(14)
  80. 2012年6月(15)
  81. 2012年5月(31)
  82. 2012年4月(24)
  83. 2012年2月(4)
  84. 2012年1月(8)
  85. 2011年12月(35)
  86. 2011年11月(32)
  87. 帝皇彩票官网2011年10月(13)
  88. 2011年8月(1)
  89. 2011年6月(1)
订阅Rss
迪士尼彩乐园 博发彩票登陆 大象彩票登入 山东群英会app下载 博发彩票登陆 帝皇彩票开奖 桔子彩票注册 新疆喜乐彩走势图 湖南快乐十分官网 帝皇彩票平台