问题
在我们的 vue 项目中(特别是后台系统),总会出现一些需要多业务线共同开发同一个项目的场景,如果各业务团队向项目中提供一些公共业务组件,但是这些组件并不能和项目一起打包,因为项目中不能因为某个私有模块的频繁变更而重复构建发布。
^_^不建议在生产环境使用,代码包含eval
思路
在这种场景下我们需要将公共的业务组件部署到服务端,由客户端请求并渲染组件。
服务端解析.vue文件
使用vue-template-compiler 模板解析器,解析SFC(单文件组件)
const compile = require('vue-template-compiler')// 获取sfc组件的源码const str = fs.readFileSync(path.resolve(__dirname, `../components/sfc.vue`), 'utf-8')// vue-loader内置,现在用来解析SFC(单文件组件)let sfc = compile.parseComponent(str)// 获取sfc组件配置let sfcOptions = getComponentOption(sfc)
getComponentOption 获取sfc组件配置
import { uuid } from 'utilscore'import stylus from 'stylus'import sass from 'sass'import less from 'less'const getComponentOption = sfc => { // 生成data-u-id const componentId = uuid(8, 16).toLocaleLowerCase() // 标签添加data-u-id属性 const template = sfc.template ? tagToUuid(sfc.template.content, componentId) : '' // 转化style(less、sass、stylus) let styles = [] sfc.styles.forEach(sty => { switch (sty.lang) { case 'stylus': stylus.render(sty.content, (err, css) => styles.push(formatStyl(sty, css, componentId))) break; case 'sass': case 'scss': styles.push(formatStyl(sty, sass.renderSync({ data: sty.content }).css.toString(), componentId)) break; case 'less': less.render(sty.content, (err, css) => styles.push(formatStyl(sty, css, componentId))) break; } }) let options = { script: sfc.script ? $require(null, sfc.script.content) : {}, styles, template } return JSON.stringify(options, (k, v) => { if(typeof(v) === 'function') { let _fn = v.toString() return /^function()/.test(_fn) ? _fn : fn.replace(/^/,'function ') } return v })}
tagToUuid 给template 中的标签追加data-u-id
const tagToUuid = (tpl, id) => { var pattern = /<[^//]("[^"]*"|'[^']*'|[^'">])*>/g return tpl.replace(pattern, $1 => { return $1.replace(/<([/w/-]+)/i, ($2, $3) => `<${$3} data-u-${id}`) })}
formatStyl 处理样式的scoped
const formatStyl = (sty, css, componentId) => { let cssText = css if (sty.scoped) { cssText = css.replace(/[/./w/>/s]+{/g, $1 => { if (/>>>/.test($1)) return $1.replace(//s+>>>/, `[data-u-${componentId}]`) return $1.replace(//s+{/g, $2 => `[data-u-${componentId}]${$2}`) }) } return cssText}
$require 执行其中的的 JavaScript 代码,并返回值
新闻热点
疑难解答