@itriton/webpack
Version:
[@itriton/webpack](http://itriton.icjs.ink/itriton/webpack/start/introduce.html),提供webpack相关插件
157 lines (150 loc) • 5.5 kB
JavaScript
;
var tslib = require('tslib');
var fs = require('fs');
var path = require('path');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(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) => tslib.__awaiter(this, void 0, void 0, function* () {
if (fs__namespace.existsSync(this.mainStylePath)) {
let mainStyleContent = fs__namespace.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__namespace.readFileSync(file, "utf-8");
content = this.formatCss(content);
content = this.removeGlobalStyles(content, mainStyleContent);
fs__namespace.writeFileSync(file, content);
}
fs__namespace.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__namespace.readdirSync(dir);
files.forEach((file) => {
const filePath = path__namespace.join(dir, file);
const stat = fs__namespace.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;
}
}
exports.DetachExcessStyles = DetachExcessStyles;