import { EntryBuilderHelpers, Plugin, Runner, WebpackWrapper } from '@morjs/utils'; import { CompilerUserConfig } from '../constants'; declare type CompileCSSClassNameCompressOptions = Exclude; /** * CSS 类名压缩功能 * * 使用方法: * 1. 创建实例 * const cssClassNameCompress = new CSSClassNameCompress(options) * 2. 初始化 * cssClassNameCompress.init({ cwd, ignore }) * 3. 分别在 css 和 xml 中增加对应的处理插件,并作为最后一个 * postHtml.use(cssClassNameCompress.postHtmlPlugin()) * postCss.use(cssClassNameCompress.postCssPlugin()) * * 实现方案 * * 实现原则:业务最小化兼容修改,同时保留配置选项对高级压缩方案的扩展支持 * * 压缩时机: * * 在编译开始前搜集可以压缩类名的文件,并将相应的 CSS 插件和 XML 插件分别注入到编译流程中 * * 压缩方案: * * 1. 提供轻量级(lite, 后续可以考虑更复杂的方式)的压缩方案 * 增加 mor.config.ts 中的 配置如下👇🏻 * experiments.compressCssClassName: CSSClassNameCompressOptions | false * 2. 判断 app.acss 或 app.less 中的类名,并添加为排除名单 * 也就是各个文件中涉及到 app.acss 中的类名,一律不做压缩 * 原因为:不能确定业务影响,不符合最小化的修改原则 * 这块儿的压缩可以作为后续高级压缩方案考虑的内容 * 3. 判断所有需要跳过压缩的 wxml 文件,其同名 acss 文件也跳过压缩 * 判断方式:class 或 自定义的 class 属性中 中是否使用了动态拼接 * 如 class='abc-{{c ? "d" : "e"}}' 这种 * 4. 根据前面的约束,通过一个共享的 css mapping 对象,可以不分先后的同时压缩 wxml 和 wxss * 因为不涉及到多进程,所以可以无视文件编译的先后顺序 */ export declare class CSSClassNameCompressPlugin implements Plugin { name: string; entryBuilder: EntryBuilderHelpers; webpackWrapper: WebpackWrapper; runner: Runner; classNameMappings: Map; generatedClassNames: Set; validFiles: Set; exceptClassNames: Set; options: CompileCSSClassNameCompressOptions; hasClassNameFilter: boolean; includeRegexp?: RegExp; excludeRegexp?: RegExp; idGenerator: () => string; idSize: number; idThreshold: number; dynamicClassRegExp: RegExp; dynamicClassRegExpGrained: RegExp; customClassAttrs: string[]; apply(runner: Runner): void; /** * 初始化 * @param options 压缩选项 */ initialize(options?: CompileCSSClassNameCompressOptions): void; /** * 处理所有的 xml 文件 */ processAllXmlFiles(): void; /** * 处理所有的 css 文件 */ processAllCssFiles(): void; /** * 根据空格和大括号将输入字符串分割成数组。 * @param {string} input - 待分割的字符串。 * @returns {string[]} 分割后的字符串数组。 */ splitBySpaceAndBraces(input: any): any[]; /** * 从已知的 axml 文件列表中查找可以处理的 */ collectCompressableFiles(): Promise; /** * 去除文件路径的后缀 * @param {string} filePath - 要处理的文件路径 * @returns {string} 去除后缀的文件路径 */ removeExtension(filePath: any): string; /** * 检查文件是否有效 * @param {string} filePath 文件路径 */ checkFileValid(filePath?: string): boolean; /** * 尝试添加文件 * @param {string} filePath 文件路径 * @param {string} fileContent 文件内容 */ tryAddFile(filePath: string, fileContent: string): void; /** * 判断文件是否符合条件 * 基于 exclude、include、和 文件内容中是否包含 {{ }} 来判断 * @param {string} filePath 文件路径 * @param {string} fileContent 文件内容 * @returns {boolean} 是否符合条件 */ checkFileBeforeAdd(filePath: string, fileContent: string): boolean; /** * 从全局样式中添加黑名单,黑名单中的 class 将不会被压缩 * @param {string} oldName 原有 class 名称 * @param {string} newName 新的 class 名称 */ addClassNameMapping(oldName: string, newName: string): void; /** * 生成新的 classname * @param {string} className 原有 class 名称 * @param {string} filePath 文件路径 * @returns {string} 新的 class 名称 */ fetchOrGenerateShortClassName(className: string, filePath: string): string; /** * 生成带前缀和后缀的不重复字符串 * @returns {string} 随机不重复字符串 */ generateRandomStringWithPrefixAndSurfix(): string; /** * 标记处理完成,如果 success 存在的情况下,调用 success 回调 */ done(): void; } export {};