問題
在我們的 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 代碼,并返回值
新聞熱點
疑難解答