Vue CLI3搭建组件库并实现按需引入实战操作 |
您所在的位置:网站首页 › webpack打包按需加载 › Vue CLI3搭建组件库并实现按需引入实战操作 |
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文件。 } }, } 复制代码本案例中简单写了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文件夹,内容如图所示。 在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 { } }, } 复制代码浏览器展示 在根目录下.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,使用时可以打印出来看一下。 浏览器展示 相当 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 |