首页 > 社交 > 科普中国

Vue3组件库打包指南,一次生成esm、esm

常驻编辑 科普中国 2022-10-09 组件   语句   语法   样式   函数   插件   格式   文件   目录   指南   方法

删除了不需要的目录,然后针对需要编译的文件调用了compileFile方法:sci拜客生活常识网

// varlet-cli/src/compiler/compileModule.ts
export async function compileFile(file: string) {
  isSFC(file) && (await compileSFC(file))// 编译vue文件
  isScript(file) && (await compileScriptFile(file))// 编译js文件
  isLess(file) && (await compileLess(file))// 编译less文件
  isDir(file) && (await compileDir(file))// 如果是目录则进行递归
}

分别处理三种文件,让我们一一来看。sci拜客生活常识网

编译Vue单文件

// varlet-cli/src/compiler/compileSFC.ts
import { parse } from '@vue/compiler-sfc'

export async function compileSFC(sfc: string) {
    // 读取Vue单文件内容
    const sources: string = await readFile(sfc, 'utf-8')
    // 使用@vue/compiler-sfc包解析单文件
    const { descriptor } = parse(sources, { sourceMap: false })
    // 取出单文件的每部分内容
    const { script, scriptSetup, template, styles } = descriptor
    // Varlet暂时不支持setup语法
    if (scriptSetup) {
        logger.warning(
            `
 Varlet Cli does not support compiling script setup syntax

  The error in ${sfc}`
        )
        return
    }
    // ...
}

使用@vue/compiler-sfc包来解析Vue单文件,parse方法可以解析出Vue单文件中的各个块,针对各个块,@vue/compiler-sfc包都提供了相应的编译方法,后续都会涉及到。sci拜客生活常识网

// varlet-cli/src/compiler/compileSFC.ts
import hash from 'hash-sum'

export async function compileSFC(sfc: string) {
    // ...
    // scoped
    // 检查是否存在scoped作用域的样式块
    const hasScope = styles.some((style) => style.scoped)
    // 将单文件的内容进行hash生成id
    const id = hash(sources)
    // 生成样式的scopeId
    const scopeId = hasScope ? `data-v-${id}` : ''
    // ...
}

这一步主要是检查style块是否存在作用域块,存在的话会生成一个作用域id,作为css的作用域,防止和其他样式冲突,这两个id相关的编译方法需要用到。sci拜客生活常识网

// varlet-cli/src/compiler/compileSFC.ts
import { compileTemplate } from '@vue/compiler-sfc'

export async function compileSFC(sfc: string) {
    // ...
    if (script) {
        // template
        // 编译模板为渲染函数
        const render =
              template &&
              compileTemplate({
                  id,
                  source: template.content,
                  filename: sfc,
                  compilerOptions: {
                      scopeId,
                  },
              })
  // 注入render函数
        let { content } = script
        if (render) {
            const { code } = render
            content = injectRender(content, code)
        }
        // ...
    }
}

使用@vue/compiler-sfc包的compileTemplate方法将解析出的模板部分编译为渲染函数,然后调用injectRender方法将渲染函数注入到script中:sci拜客生活常识网

// varlet-cli/src/compiler/compileSFC.ts
const NORMAL_EXPORT_START_RE = /exports+defaults+{/
const DEFINE_EXPORT_START_RE = /exports+defaults+defineComponents*(s*{/

export function injectRender(script: string, render: string): string {
  if (DEFINE_EXPORT_START_RE.test(script.trim())) {
    return script.trim().replace(
      DEFINE_EXPORT_START_RE,
      `${render}
export default defineComponent({
  render,
    `
    )
  }
  if (NORMAL_EXPORT_START_RE.test(script.trim())) {
    return script.trim().replace(
      NORMAL_EXPORT_START_RE,
      `${render}
export default {
  render,
    `
    )
  }
  return script
}

兼容两种导出方式,以一个小例子来看一下,比如生成的渲染函数为:sci拜客生活常识网

export function render(_ctx, _cache) {
    // ...
}

script的内容为:sci拜客生活常识网

export default defineComponent({
    name: 'VarButton',
    // ...
})

注入render后script的内容变成了:sci拜客生活常识网

export function render(_ctx, _cache) {
    // ...
}
export default defineComponent({
    render,
    name: 'VarButton',
    /// ...
})

其实就是把渲染函数的内容和script的内容合并了,script其实就是组件的选项对象,所以同时也把组件的渲染函数添加到组件对象上。

相关阅读:

  • iis如何安装(怎样安装iis组件)
  • 理解了状态管理,就理解了前端开发的核心​
  • Windows在中国失去了号召能力
  • 马化腾、曾毓群冲进这个全新赛道,三位清华校友刚刚拿下
  • C#开源之敏感词检测过滤组件
  • Deno
  • 前端开源之PDF在线浏览组件PDFObject.js
  • JavaGUI
  • 鸿蒙
  • Go
    • 网站地图 |
    • 声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不做权威认证,如若验证其真实性,请咨询相关权威专业人士。