解析ElementPlus打包源码(四、打包主题)

buildThemeChalk

scss 复制代码
withTaskName('buildThemeChalk', () =>
  run('pnpm run -C packages/theme-chalk build')
)

这个打包任务需要执行packages/theme-chalk下的build命令

对应的命令是"build": "gulp --require @esbuild-kit/cjs-loader"

我们去看对应的gulpfile.ts

javascript 复制代码
import path from 'path'
import { Transform } from 'stream'
import chalk from 'chalk'
import { type TaskFunction, dest, parallel, series, src } from 'gulp'
import gulpSass from 'gulp-sass'
import dartSass from 'sass'
import autoprefixer from 'gulp-autoprefixer'
import rename from 'gulp-rename'
import consola from 'consola'
import postcss from 'postcss'
import cssnano from 'cssnano'
import { epOutput } from '@element-plus/build-utils'
import type Vinly from 'vinyl'

const distFolder = path.resolve(__dirname, 'dist')
const distBundle = path.resolve(epOutput, 'theme-chalk')

/**
 * using `postcss` and `cssnano` to compress CSS
 * @returns
 */
function compressWithCssnano() {
  const processor = postcss([
    cssnano({
      preset: [
        'default',
        {
          // avoid color transform
          colormin: false,
          // avoid font transform
          minifyFontValues: false,
        },
      ],
    }),
  ])
  return new Transform({
    objectMode: true,
    transform(chunk, _encoding, callback) {
      const file = chunk as Vinly
      if (file.isNull()) {
        callback(null, file)
        return
      }
      if (file.isStream()) {
        callback(new Error('Streaming not supported'))
        return
      }
      const cssString = file.contents!.toString()
      processor.process(cssString, { from: file.path }).then((result) => {
        const name = path.basename(file.path)
        file.contents = Buffer.from(result.css)
        consola.success(
          `${chalk.cyan(name)}: ${chalk.yellow(
            cssString.length / 1000
          )} KB -> ${chalk.green(result.css.length / 1000)} KB`
        )
        callback(null, file)
      })
    },
  })
}

/**
 * compile theme-chalk scss & minify
 * not use sass.sync().on('error', sass.logError) to throw exception
 * @returns
 */
function buildThemeChalk() {
  const sass = gulpSass(dartSass)
  const noElPrefixFile = /(index|base|display)/
  return src(path.resolve(__dirname, 'src/*.scss'))
    .pipe(sass.sync())
    .pipe(autoprefixer({ cascade: false }))
    .pipe(compressWithCssnano())
    .pipe(
      rename((path) => {
        if (!noElPrefixFile.test(path.basename)) {
          path.basename = `el-${path.basename}`
        }
      })
    )
    .pipe(dest(distFolder))
}

/**
 * Build dark Css Vars
 * @returns
 */
function buildDarkCssVars() {
  const sass = gulpSass(dartSass)
  return src(path.resolve(__dirname, 'src/dark/css-vars.scss'))
    .pipe(sass.sync())
    .pipe(autoprefixer({ cascade: false }))
    .pipe(compressWithCssnano())
    .pipe(dest(`${distFolder}/dark`))
}

/**
 * copy from packages/theme-chalk/dist to dist/element-plus/theme-chalk
 */
export function copyThemeChalkBundle() {
  return src(`${distFolder}/**`).pipe(dest(distBundle))
}

/**
 * copy source file to packages
 */

export function copyThemeChalkSource() {
  return src(path.resolve(__dirname, 'src/**')).pipe(
    dest(path.resolve(distBundle, 'src'))
  )
}

export const build: TaskFunction = parallel(
  copyThemeChalkSource,
  series(buildThemeChalk, buildDarkCssVars, copyThemeChalkBundle)
)

export default build

copyThemeChalkSource

我们直接运行pnpm run -C packages/theme-chalk build

可以看到这个把src下的文件,直接复制到了const distBundle = path.resolve(epOutput, 'theme-chalk')这个路径下

series(buildThemeChalk, buildDarkCssVars, copyThemeChalkBundle)

按顺序执行了 buildThemeChalk, buildDarkCssVars, copyThemeChalkBundle 这几个任务

javascript 复制代码
function buildThemeChalk() {
  const sass = gulpSass(dartSass)
  const noElPrefixFile = /(index|base|display)/
  return src(path.resolve(__dirname, 'src/*.scss'))
    .pipe(sass.sync())
    .pipe(autoprefixer({ cascade: false }))
    .pipe(compressWithCssnano())
    .pipe(
      rename((path) => {
        if (!noElPrefixFile.test(path.basename)) {
          path.basename = `el-${path.basename}`
        }
      })
    )
    .pipe(dest(distFolder))
}
  • gulp-sass:是gulp的sass插件,可以点击链接查看相关文档说明
  • sass.sync():是同步编译scss成css。调用 sass()(用于异步渲染 CSS),调用 sass.sync()(用于同步渲染 CSS)
  • gulp-autoprefixergulp-autoprefixer 是一个基于 Gulp 的插件,用于自动为 CSS 代码添加浏览器兼容前缀,从而解决不同浏览器对 CSS 属性支持差异的问题。也可以点击链接查看相关文档说明
  • compressWithCssnano():
    • 通过 PostCSS 结合 cssnano 对 CSS 内容进行压缩优化。colormin: false禁用颜色压缩(避免如 #ffffff 被转为 white,或 rgba 被简化)。minifyFontValues: false:禁用字体值压缩,可见minifyFontValues的文档说明。
    • 函数返回了一个 Transform 流
      • objectMode: true,Gulp 处理的是文件对象而非二进制流,需开启对象模式
      • file.isNull()是边界判断,空文件直接返回
      • file.isStream()也是边界判断,流式文件直接报错
      • 然后 使用 PostCSS 处理器处理 CSS 字符串,
  • rename:使用gulp-rename插件对文件进行重命名

对于 buildDarkCssVars,就是针对暗色主题变量进行打包

对于 copyThemeChalkBundle,把主题打包的相关css文件复制到最终的打包目录const distBundle = path.resolve(epOutput, 'theme-chalk')

copyFullStyle

该任务把打包后的theme-chalk下的index.css复制到了如图这里

相关推荐
东风破_6 小时前
danci 项目(三):从 JSON 数据到 AI Coding,真实项目里的数据清洗、Prompt 和工程规范
前端·后端·node.js
东风破_6 小时前
danci 项目(一):从需求到架构,一个单词学习系统为什么会这样设计
前端·后端·node.js
蒲公英eric7 小时前
从客户端到服务端:DVWA DOM 型 XSS 模块完整漏洞分析教程
前端·web安全·ai·xss·dvwa·ai安全
单线程_017 小时前
从案例分析 Vue3 Tokenizer+Parser 源码三
前端·javascript·vue.js
顶点多余7 小时前
那些在算法中适合巩固的知识点---1
java·前端·算法
Setsuna_F_Seiei8 小时前
前端转型 Agent 开发 03 之 Agent Tools - 给 Agent 装上手脚
前端·agent·ai编程
jay神8 小时前
【计算机毕业设计】基于SpringBoot的程序教学辅助系统
java·前端·vue.js·spring boot·后端·毕业设计·课程设计
小磊哥er9 小时前
深入解构Claude Code - 第 8 篇 · 数据放哪、钱怎么算
javascript·ai编程
kyriewen10 小时前
我装了30多个Skill,给AI安排了8个岗位
前端·javascript·ai编程
风骏时光牛马11 小时前
大模型落地实践中的技术选型思路与方案对比
前端