@itriton/webpack
Version:
[@itriton/webpack](http://itriton.icjs.ink/itriton/webpack/start/introduce.html),提供webpack相关插件
135 lines (131 loc) • 4.84 kB
JavaScript
import { __awaiter } from 'tslib';
import * as fs from 'fs';
import * as path from 'path';
const cssbeautify = require("cssbeautify");
class DetachExcessStyles {
/**
* 创建DetachExcessStyles实例
* @param {DetachExcessStylesOptions} options - 插件 options.
* @example
* ``` typescript
const path = require('path');
const { DetachExcessStyles } = require('@itriton/webpack');
const env = process.env.NODE_ENV === 'development' ? 'dev' : 'build';
const mainStylePath = path.join(__dirname, `unpackage/dist/${env}/mp-weixin/common/main.wxss`);
const baseDir = path.join(__dirname, `unpackage/dist/${env}/mp-weixin`);
let plugins = [];
if (process.env.UNI_PLATFORM === 'mp-weixin') {
plugins.push(
new DetachExcessStyles({
mainStylePath,
baseDir,
startWithDir: ['pages'], // 支持多个起始目录
endWithFile: '.wxss', // 可选,默认为 '.wxss'
fullMatch: false, // 可选,默认为 false,设置为 true 时全匹配起始目录文件夹名称
debug: true // 可选,默认为 false
})
)
}
module.exports = {
configureWebpack: {
plugins
}
}
* ```
*/
constructor(options) {
this.mainStylePath = options.mainStylePath;
this.baseDir = options.baseDir;
this.startWithDir = Array.isArray(options.startWithDir) ? options.startWithDir : [options.startWithDir || "pages"];
this.endWithFile = options.endWithFile || ".wxss";
this.fullMatch = options.fullMatch || false;
this.debug = options.debug || false;
}
apply(compiler) {
compiler.hooks.done.tapPromise("DetachExcessStyles", (stats) => __awaiter(this, void 0, void 0, function* () {
if (fs.existsSync(this.mainStylePath)) {
let mainStyleContent = fs.readFileSync(this.mainStylePath, "utf-8");
mainStyleContent = this.formatCss(mainStyleContent);
const xxssFiles = this.getAllXxssFiles(this.baseDir);
if (this.debug)
console.log(xxssFiles);
for (const file of xxssFiles) {
let content = fs.readFileSync(file, "utf-8");
content = this.formatCss(content);
content = this.removeGlobalStyles(content, mainStyleContent);
fs.writeFileSync(file, content);
}
fs.writeFileSync(this.mainStylePath, mainStyleContent);
}
}));
}
/**
* Get all .xxss files in the specified directory.
* @param {string} dir - The directory to search.
* @param {boolean} [further=false] - Whether to continue searching deeper directories.
* @returns {string[]} - An array of file paths.
*/
getAllXxssFiles(dir, further = false) {
let results = [];
const files = fs.readdirSync(dir);
files.forEach((file) => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
const shouldRecurse = this.startWithDir.some((startDir) => this.fullMatch ? file === startDir : file.startsWith(startDir));
if (shouldRecurse || further) {
results = results.concat(this.getAllXxssFiles(filePath, true));
}
} else if (stat.isFile() && file.endsWith(this.endWithFile)) {
results.push(filePath);
}
});
return results;
}
/**
* Remove global styles from the content.
* @param {string} content - The content to process.
* @param {string} mainStyleContent - The global styles to remove.
* @returns {string} - The processed content.
*/
removeGlobalStyles(content, mainStyleContent) {
const mainStyles = mainStyleContent.split("\n").map((line) => line.trim()).filter((line) => line);
const mainStyleSet = new Set(mainStyles);
const contentLines = content.split("\n");
const resultLines = [];
let inRemoveBlock = false;
for (const line of contentLines) {
const trimmedLine = line.trim();
if (mainStyleSet.has(trimmedLine)) {
if (trimmedLine.endsWith("{")) {
inRemoveBlock = true;
}
continue;
}
if (inRemoveBlock) {
if (trimmedLine.endsWith("}")) {
inRemoveBlock = false;
}
continue;
}
resultLines.push(line);
}
return resultLines.join("\n");
}
/**
* Format CSS content.
* @param {string} css - The CSS content to format.
* @returns {string} - The formatted CSS content.
*/
formatCss(css) {
css = css.replace(/\/\*[\s\S]*?\*\//g, "");
css = cssbeautify(css, {
indent: " ",
autosemicolon: true
});
css = css.replace(/\{(\s*)/g, "{ ").replace(/\s+/g, " ").trim();
css = css.replace(/\}/g, "}\n");
return css;
}
}
export { DetachExcessStyles };