解析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复制到了如图这里

相关推荐
LYFlied1 天前
【每日算法】LeetCode215. 数组中的第K个最大元素
前端·算法
怎么就重名了1 天前
Kivy的KV语言总结
前端·javascript·html
代码猎人1 天前
类数组对象是什么,如何转化为数组
前端
duanyuehuan1 天前
js 解构赋值
开发语言·前端·javascript
进击的野人1 天前
Vue3 响应式系统深度解析:从原理到实践
前端·vue.js·前端框架
南山安1 天前
JavaScript 性能优化:防抖和节流
javascript·面试·程序员
计算机程序设计小李同学1 天前
汽车4S店管理系统设计与实现
前端·spring boot·学习
SoraYama1 天前
🚀 TypeScript 5.9:import defer 来袭
前端·typescript
YaeZed1 天前
Vue3-Teleport
前端·vue.js