仿ElementUI构建自己的Vue组件库用babel-plugin-component按需加载组件及自定义SASS主题...

本文介绍如何使用VueCLI3.0和Babel插件构建组件库,并实现按需加载,有效减小项目体积,加快加载速度。通过详细步骤和代码示例,展示如何配置项目结构、组件及样式文件,以及如何发布到npm。

最近使用ElementUI做项目的时候用Babel的插件babel-plugin-component做按需加载,使得组件打包的JS和CSS包体积大大缩小,加载速度也大大提升,所有想模仿做一个组件库也来做下按需加载。

首先用Vue CLI 3.0新建一个项目
vue create bes-ui
复制代码

注意的是cli3的脚手架用的Babel7的配置,只有babel.config.js文件,所以要自己添加.babelrc文件。

项目结构

新建项目之后,可以按照自己的想法建文件结构,也可以按照babel-plugin-component官方文档的目录构建:

上面有两种方式,前一种是组件单一主题方式,后一种是主题库的方式,大家可以自己选择,下图是bes-ui的目录结构:
这里大概介绍下文件用途: -dist:组件库测试项目打包文件 -examples:组件库的测试项目 -lib:组件库的源码 -local:组件库的国际化文件 -package:组件库打包后的压缩的js,css文件 -static:组件库的静态资源(css主题) 其他文件就不介绍了,都是脚手架生成的文件

组件介绍

这里组件库写了两个样例:component1,component2 。 每个组件都添加了自己的初始化install方法(用于按需加载时候独立使用),install方面里面加个日志,方便后面看看组件加载记录。

最外面添加整体加载用的index.js,用于一次性加载所有项目
最后就是组件的样式文件了(这里的base.css和index.css都是必须的,官方的api有有标注):
大家注意的一点是组件包名一定要叫 “ lib ” ,样式文件的路径和名字大家可以随意,到时候在配置文件里面引用对应的路径就行,我这里叫static,里面一定要加 base.css和index.css,这都是babel-plugin-component的API里面标注了,当然大家也可以看babel-plugin-component的源码core.js【位置在node_modules/babel-plugin-component/lib/core.js】里面有涉及到获取对应文件:

if (styleLibrary && _typeof(styleLibrary) === 'object') {//这个是样式的一些配置
  styleLibraryName = styleLibrary.name;
  isBaseStyle = styleLibrary.base;
  modulePathTpl = styleLibrary.path;
  mixin = styleLibrary.mixin;
  styleRoot = styleLibrary.root;
}

if (styleLibraryName) {//是否在.babelrc配置了styleLibraryName
  if (!cachePath[libraryName]) {//是否存在配置好的样式获取路径
    var themeName = styleLibraryName.replace(/^~/, '');
    cachePath[libraryName] = styleLibraryName.indexOf('~') === 0 ?//路径是否相对于element-ui/lib
    resolve(process.cwd(), themeName) : 
    "".concat(libraryName, "/").concat(libDir, "/").concat(themeName);
  }//如果是相对于lib   组合路径---element-ui/lib/theme-chalk/   这个目录下是75个css文件
  //这里将这一段路径保存在了cachePath[libraryName]  后续会用到

  if (libraryObjs[methodName]) {//作者也没搞清楚这里是什么  不过没关系,事实证明这里走了false
    /* istanbul ingore next */
    if (cache[libraryName] === 2) {
      throw Error('[babel-plugin-component] If you are using both' + 'on-demand and importing all, make sure to invoke the' + ' importing all first.');
    }

    if (styleRoot) {//这里默认是没有配置的  所有走false
      path = "".concat(cachePath[libraryName]).concat(styleRoot).concat(ext);
    } else {
      path = "".concat(cachePath[libraryName]).concat(_root || '/index').concat(ext);
    }//这里会默认先加载index.css  因为ext没设置就会默认css

    cache[libraryName] = 1;
  } else {//走了else
    if (cache[libraryName] !== 1) {//这里肯定是不等于1,因为上面一行才会赋值1
      /* if set styleLibrary.path(format: [module]/module.css) */
      var parsedMethodName = parseName(methodName, camel2Dash);

      if (modulePathTpl) {
        var modulePath = modulePathTpl.replace(/\[module]/ig, parsedMethodName);
        path = "".concat(cachePath[libraryName], "/").concat(modulePath);
      } else {//这里走了else 也就是样式路径后续为模块名.[ext]
        path = "".concat(cachePath[libraryName], "/").concat(parsedMethodName).concat(ext);
      }//所有这里的路径就是element-ui/lib/

      if (mixin && !isExist(path)) {
        path = style === true ? "".concat(_path, "/style").concat(ext) : "".concat(_path, "/").concat(style);
      }

      if (isBaseStyle) {
        addSideEffect(file.path, "".concat(cachePath[libraryName], "/base").concat(ext));
      }

      cache[libraryName] = 2;
    }
  }

  addDefault(file.path, path, {
    nameHint: methodName
  });
} else {
  if (style === true) {
    addSideEffect(file.path, "".concat(path, "/style").concat(ext));
  } else if (style) {
    addSideEffect(file.path, "".concat(path, "/").concat(style));
  }
}
}
复制代码

转回正题,文件创建好了之后,就可以发包到npm了,这里提供了两种方式:1是将组件库打包压缩成css和js,暴露出去(这种方式无法做按需,因为所以代码压缩在一起了);2是将lib下的index暴露出去(这种方式可以做按需加载);如下(package文件):

组件使用

组件放上去后,就可以在项目里面使用了,这里用vue create添加了一个example项目:

项目加载bes-ui:
项目使用bes-ui(这里只加载了component2):
启动项目后,观察加载的项目日志:
这里日志打印的只加载了component2,如果还不放心的话可以看下style标签是不是只有component2的css:
这里确实只有component2的样式, 这里有个问题就是样式加载了两遍 这里主要是组件内部加载了一次样式,babel-plugin-component的按需又加载了一次,这里主要是为了测试两种不同方式,(组件内的加载样式是给压缩js和css用的)如果做按需的话就可以去掉了:
这里贴下Babel的配置:

总结

最后可以打个测试项目包,看下里面确实没有其他组件的代码和样式,这里就不贴图了,大家可以自己尝试,总结下这里的bes-ui其实就是模仿ElementUI的一个简易的组件库(虽然目前只加了按需加载,后续可以把国际化和主题加上),项目里面的一些配置和文件都大同小异,如果有兴趣构建自己的vue组件库的时候,bes-ui是个不错的模版。

GitHub项目地址:github.com/BothEyes199…

转载于:https://juejin.im/post/5cbd45436fb9a031ef63b6e7

### @vue/cli-plugin-babel 4.5.19 兼容的 Node.js 版本范围 `@vue/cli-plugin-babel@4.5.19` 是 Vue CLI 的一部分,其兼容性主要取决于 `@vue/cli-service` 和其他依赖项的要求。根据已知的信息以及常见的 Vue CLI 配置[^2],可以推断出该版本通常支持以下 Node.js 版本范围: #### 节点版本范围 - **Node.js v8.x 到 v14.x**:这是大多数 Vue CLI 3Vue CLI 4 插件所推荐的节点版本区间。 - 更具体地说,Vue CLI 官方文档建议使用 LTS(长期支持)版本的 Node.js 来确保最佳兼容性和稳定性。 对于 `@vue/cli-plugin-babel@4.5.19`,它明确声明了对 `@vue/cli-service@"^3.0.0 || ^4.0.0-0"` 的 peerDependency 支持。这意味着它的设计目标是对齐于这些服务版本的需求,而这些服务版本本身也倾向于较低的 Node.js 版本需求。 如果尝试运行更高版本的 Node.js (如 v16 或以上),可能会遇到插件冲突或其他错误,正如引用中的描述所示。因此,在这种情况下,降级到 Node.js v14.x 或更低版本通常是解决问题的有效方法。 以下是调整后的代码片段用于验证环境配置是否正确: ```javascript // package.json 中的 dependencies 和 devDependencies 应保持一致 { "dependencies": { "node-sass": "^4.13.1", "sass-loader": "^7.3.1" }, "devDependencies": { "@vue/cli-plugin-babel": "~4.5.15" } } ``` 此外,当出现类似于 `"Could not resolve '@vue/cli-plugin-babel/preset'"` 这样的错误时,可以通过修改或注释掉 Babel 配置来绕过问题[^4]。然而,这仅作为临时解决方案;根本上仍需确认 Node.js 和相关包管理工具的版本一致性。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值