Vue CLI3搭建组件库并实现按需引入实战操作

您所在的位置:网站首页 webpack打包按需加载 Vue CLI3搭建组件库并实现按需引入实战操作

Vue CLI3搭建组件库并实现按需引入实战操作

2023-10-07 08:18| 来源: 网络整理| 查看: 265

Vue CLI3搭建组件库并实现按需引入实战操作

在Vue CLI3搭建组件库并用npm发布实战操作中介绍了单个组件的组件库怎么开发,本文将一步一步教大家怎么开发多个组件集成的组件库,怎么实现组件库按需引入。觉得有用点个赞支持一下。

本文将略过安装Vue CLI3、搭建组件库的项目、清洁组件库项目的步骤,不懂的地方可以看Vue CLI3搭建组件库并用npm发布实战操作

一、建立两个git仓库放本文的示例代码 组件库引用组件库demo 二、组件库项目中webpack一些基础配置

在Vue CLI3中,项目的webpack配置是要在根目录下新建vue.config.js来配置。

1、区分开发环境和生成环境的配置

因为多入口组件库中开发环境和生成环境的配置是不同,所有要区分开来。 通过process.env.NODE_ENV变量来判断,生产环境时process.env.NODE_ENV为development。

//开发环境配置 const devConfig = { //... } const buildConfig = { //... } module.exports = process.env.NODE_ENV === 'development' ? devConfig : buildConfig; 复制代码 2、更改src文件夹的名字

在Vue组件库项目中原来src文件夹的内容是demo展示的内容,所以文件名改成examples,比较形象。

3、重新配置项目入口文件

在vue.config.js文件中配置内容如下:

const devConfig={ pages: { index: { entry: 'examples/main.js', template: 'public/index.html', filename: 'index.html', }, }, } 复制代码 4、配置文件别名

文件别名会在写demo中用到。在vue.config.js文件中配置内容如下:

const path = require('path'); function resolve(dir) { return path.resolve(__dirname, dir) } const devConfig = { configureWebpack: { resolve: { extensions: ['.js', '.vue', '.json'], alias: { '@': resolve('packages'), 'assets': resolve('examples/assets'), 'views': resolve('examples/views'), } }, }, } 复制代码 5、配置devServer项

在vue.config.js文件中配置内容如下:

const devConfig = { devServer:{ port: 8091,//固定端口 hot: true,//开启热更新 open: 'Google Chrome'//固定打开浏览器 } } 复制代码 6、在根目录下新建packages文件夹

组件的代码在packages文件夹中开发

7、将新增的packages文件夹加入babel转码编译

在vue.config.js文件中配置内容如下:

const devConfig = { chainWebpack: config => { config.module .rule('js') .include .add('/packages') .end() .use('babel') .loader('babel-loader') .tap(options => { return options }) }, } 复制代码

以上是开发环境的配置,下面来写一下生产环境的配置

8、在生产环境下也要将新增的packages文件夹加入babel转码编译 const buildConfig = { chainWebpack: config => { config.module .rule('js') .include .add('/packages') .end() .use('babel') .loader('babel-loader') .tap(options => { return options }) }, } 复制代码 9、配置生产环境构建文件的目录

我们将组件库打包编译后放在lib文件夹中,在vue.config.js文件中配置内容如下:

const buildConfig = { outputDir: 'lib', } 复制代码 10、关闭source map

关闭source map有两个好处

减少打包编译的时间;避免在生产环境中用F12开发者工具在Sources中看到源码。

在vue.config.js文件中配置内容如下:

const buildConfig = { productionSourceMap: false, } 复制代码 三、多入口文件页面打包配置

在Vue CLI3搭建的项目中借助babel-plugin-import这个webpack插件并且配置babel.config.js,来实现组件库的按需引入的前提是组件库是多入口文件页面打包的。

1、配置entry

在Vue CLI3中是在configureWebpack选项的entry属性上配置项目多入口,在本文案例中,配置如下

const buildConfig = { configureWebpack: { entry: { index: 'D:\\project\\02npm\\02Vue_Cli3_MAPLib\\packages\\index.js', testA: 'D:\\project\\02npm\\02Vue_Cli3_MAPLib\\packages\\testA\\index.js', testB: 'D:\\project\\02npm\\02Vue_Cli3_MAPLib\\packages\\testB\\index.js' }, }, } 复制代码

但是以上每个入口都是写死的,所以我们要利用nodejs实现自动化配置。

首先我们引入nodejs中path模块来处理文件路径。

const path = require('path'); const join = path.join;//拼接路径 复制代码

写一个把目标路径按当前文件路径转成绝对路径的方法

function resolve(dir) { return path.resolve(__dirname, dir) } 复制代码

其中__dirname是当前文件所在目录的完整绝对路径,例

还要引入nodejs中fs模块在处理文件信息

const fs = require('fs'); 复制代码

我们建一个函数getEntries(path),其中path是组件代码所在的文件夹名称,返回一个对象entries,key为每个组件文件夹的名称,值为每个组件文件夹中入口文件index.js的绝对路径。

首先使用fs.readdirSync(resolve(path))获取到组件代码所在的文件夹目录下所有文件名称,存在files变量中。

然后用数组reduce()方法循环files,先将每个文件名(item)利用join(path, item)转成路径存到itemPath变量。

用fs.statSync(itemPath).isDirectory()对每个文件进行判断是不是文件夹。

如果是文件夹,先把itemPath和入口文件index.js拼接成一个地址,再转成绝对路径,将item作为key,赋值到返回对象上

entries[item] = resolve(join(itemPath, 'index.js'))。 复制代码

如果不是文件夹,直接把itemPath转成绝对路径,将item去除后缀作为key,赋值到返回对象上

const [name] = item.split('.') entries[name] = resolve(`${itemPath}`) 复制代码

下面是完整代码

function getEntries(path) { let files = fs.readdirSync(resolve(path)); const entries = files.reduce((ret, item) => { const itemPath = join(path, item) const isDir = fs.statSync(itemPath).isDirectory(); if (isDir) { ret[item] = resolve(join(itemPath, 'index.js')) } else { const [name] = item.split('.') ret[name] = resolve(`${itemPath}`) } return ret }, {}) return entries } 复制代码

比如在本文案例中,执行getEntries('packages')将会得到一个对象

{ index: 'D:\\project\\02npm\\02Vue_Cli3_MAPLib\\packages\\index.js', testA: 'D:\\project\\02npm\\02Vue_Cli3_MAPLib\\packages\\testA\\index.js', testB: 'D:\\project\\02npm\\02Vue_Cli3_MAPLib\\packages\\testB\\index.js' }, 复制代码

利用对象展开运算符,配置entry

const buildConfig = { configureWebpack: { entry: { ...getEntries('packages'), }, }, } 复制代码 2、配置output filename: 配置每个组件打包后生成对应文件名称,多入口文件配置为[name].index.js,为什么配置这个名称后面会解释。libraryTarget:配置为commonjs2,入口文件的返回值将分配给module.exports对象,使其组件库在webpack构建的环境下使用,这个是关键。 const buildConfig = { configureWebpack: { output: { filename: '[name]/index.js', libraryTarget: 'commonjs2', } }, } 复制代码 3、样式打包配置

在css.extract.filename上配置样式打包路径和文件名称

const buildConfig = { css: { sourceMap: true, extract: { filename: 'style/[name].css'//在lib文件夹中建立style文件夹中,生成对应的css文件。 } }, } 复制代码

4、删除Vue CLI3原先打包编译的一些无用功能 删除splitChunks,因为每个组件是独立打包,不需要抽离每个组件的公共js出来。删除copy,不要复制public文件夹内容到lib文件夹中。删除html,只打包组件,不生成html页面。删除preload以及prefetch,因为不生成html页面,所以这两个也没用。删除hmr,删除热更新。删除自动加上的入口App。 const buildConfig = { chainWebpack: config => { config.optimization.delete('splitChunks') config.plugins.delete('copy') config.plugins.delete('html') config.plugins.delete('preload') config.plugins.delete('prefetch') config.plugins.delete('hmr') config.entryPoints.delete('app') }, } 复制代码 5、配置字体的loader const buildConfig = { chainWebpack: config => { config.module .rule('fonts') .use('url-loader') .tap(option => { option.fallback.options.name = 'static/fonts/[name].[hash:8].[ext]' return option }) }, } 复制代码 四、组件库开发

本案例中简单写了testA和testB两个组件来供测试

1、packages目录结构

主要讲一下组件入口文件怎么编写,其它跟平时开发一样。

2、单个组件入口

以组件testA为例,对外暴露一个对象test,并提供 install 方法,外部就可以通过Vue.use()来调用这个组件。

import test from './src/index.vue'; test.install = function(Vue) { Vue.component(test.name, test); }; export default test; 复制代码 3、组件库总入口 import testA from './testA' import testB from './testB' export default { install(Vue) { Vue.use(testA); Vue.use(testB) }, } 复制代码 五、编译打包

执行npm run build,打包编译后,在项目中会得到一个lib文件夹,内容如图所示。

六、npm发布前准备工作 1、配置主入口文件

在package.json文件中写入:

"main": "lib/index/index.js", 复制代码 2、其他配置

可以参考Vue CLI3搭建组件库并用npm发布实战操作

七、按需引入配置 1、引入组件

发布好后(如果不会发布请看Vue CLI3搭建组件库并用npm发布实战操作),在引用组件库demo中,执行npm install [email protected] --save安装组件库。

在执行npm install babel-plugin-import --save-dev安装babel-plugin-import插件,利用它实现组件按需引入。

在根目录下.babelrc.js文件中按如下配置

module.exports = { "presets": ["@vue/app"], "plugins": [ [ "import", { "libraryName": "map-lib-test",//组件库名称 "camel2DashComponentName": false,//关闭驼峰自动转链式 "camel2UnderlineComponentName": false//关闭蛇形自动转链式 } ], ] } 复制代码

在main.js写入

import { testA, testB } from 'map-lib-test'; Vue.use(testA); Vue.use(testB); 复制代码

在src/views/demo.vue引用

export default { data() { return { } }, } 复制代码

浏览器展示

2、引入样式

在根目录下.babelrc.js文件中按如下配置

module.exports = { "presets": ["@vue/app"], "plugins": [ [ "import", { "libraryName": "map-lib-test",//组件库名称 "camel2DashComponentName": false,//关闭驼峰自动转链式 "camel2UnderlineComponentName": false//关闭蛇形自动转链式 "style": (name) =>{ const cssName = name.split('/')[2]; return `map-lib-test/lib/style/${cssName}.css` } } ], ] } 复制代码

style的值为函数时,babel-plugin-import将自动导入文件路径等于函数返回值的文件。组件库打包后的css文件的路径如下图所示。故如上述代码所配置。其中style的值为函数时,其参数name的值的示例为map-lib-test/lib/testA,使用时可以打印出来看一下。 

浏览器展示

八、注意点 1、 为什么是import{testA,testB}而不是import{testC,testD} 如果是`import {testC ,testD }`,会发生如下报错 复制代码

import { testA, testB } from 'map-lib-test'; 复制代码

相当

import testA from "map-lib-test/lib/testA"; import testB from "map-lib-test/lib/testB"; 复制代码 import { testC, testD } from 'map-lib-test'; 复制代码

相当

import testC from "map-lib-test/lib/testC"; import testB from "map-lib-test/lib/testD"; 复制代码

map-lib-test/lib中没有testC、testD这个文件,所以就报以上错误。

那为什么是import{testA , testB},还记得在多入口文件页面打包配置中配置entry时,entry对象每个key是每个组件代码所在的文件夹名,而output.filename是'[name]/index.js'。每个组件是独立打包,打包生成文件夹名称是原来每个组件代码所在文件夹名称。

这样是不是很清楚,为什么要import{testA , testB},是因为testA和testB两组件打包生成文件夹名分别是testA和testB。

以上还可以说明为什么output.filename是'[name]/index.js'而不是'[name]/main.js'或者而不是'[name]/out.js'

因为import testA from "map-lib-test/lib/testA";默认相当import testA from "map-lib-test/lib/testA/index.js";

所以在写组件使用文档时,一定要写明按需引入时,是import{testA , testB}的。

2、组件标签

为什么是,而不是。 看一下testA组件的入口文件中有写这么一段代码

import test from './src/index.vue'; test.install = function(Vue) { Vue.component(test.name, test); }; 复制代码

在Vue中注册以test.name为名称的组件,而test.name就是testA组件中name选项的值。

 

如果不需按需加载需单独引入css样式:如,import 'mulit-npm/lib/style/index.css'

 

 

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3