Skip to content

Commit 5027298

Browse files
committed
fix: Re-use precomiled css if available. Give compiled css to optimizer.
1 parent 994239b commit 5027298

File tree

6 files changed

+45
-16
lines changed

6 files changed

+45
-16
lines changed

packages/@css-blocks/core/src/BlockParser/BlockFactory.ts

+1
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ export class BlockFactory {
365365
const block = await this.parser.parseDefinitionSource(definitionAst, file.identifier, file.blockId, file.defaultName);
366366

367367
// Merge the rules from the CSS contents into the Block.
368+
block.precompiledStylesheet = cssContentsAst;
368369
this._mergeCssRulesIntoDefinitionBlock(block, cssContentsAst, file);
369370

370371
// And we're done!

packages/@css-blocks/core/src/BlockTree/Block.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ export class Block
7878
* primarily for error reporting, if present.
7979
*/
8080
public stylesheet: postcss.Root | undefined;
81+
/**
82+
* The PostCSS AST of the compiled CSS this block was built from.
83+
* If this is set, the stylesheet property is only the definition file contents.
84+
*/
85+
public precompiledStylesheet: postcss.Root | undefined;
8186
public blockReferencePaths: Map<string, Block>;
8287

8388
/**
@@ -90,12 +95,13 @@ export class Block
9095
* responsible for enforcing uniqueness.)
9196
* @param stylesheet - The PostCSS AST of the stylesheet this block is built from.
9297
*/
93-
constructor(name: string, identifier: FileIdentifier, guid: string, stylesheet?: postcss.Root) {
98+
constructor(name: string, identifier: FileIdentifier, guid: string, stylesheet?: postcss.Root, precompiledStylesheet?: postcss.Root) {
9499
super(name);
95100
this._identifier = identifier;
96101
this._dependencies = new Set<string>();
97102
this.rootClass = new BlockClass(ROOT_CLASS, this);
98103
this.stylesheet = stylesheet;
104+
this.precompiledStylesheet = precompiledStylesheet;
99105
this.guid = guid;
100106

101107
this.addClass(this.rootClass);

packages/@css-blocks/core/test/BlockFactoryCompiledCssFiles/basic-test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ export class BlockFactoryCompiledCssFilesTests {
145145
await factory.getBlock(importer.identifier(null, navCssPath, config));
146146
return this.assertError(
147147
CssBlockError,
148-
"[css-blocks] Error: Block uses a name that has already been used! Check dependencies for conflicting block names. (foo/bar/other.css)",
148+
"[css-blocks] Error: Block uses a name that has already been used by foo/bar/nav.css (foo/bar/other.css)",
149149
factory.getBlock(importer.identifier(null, otherCssPath, config)),
150150
);
151151
}

packages/@css-blocks/ember-app/src/brocolli-plugin.ts

+32-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Analyzer, Block, BlockFactory, Options as CSSBlocksOptions, SerializedSourceAnalysis, resolveConfiguration } from "@css-blocks/core";
1+
import { Analyzer, Block, BlockFactory, Options as CSSBlocksOptions, SerializedSourceAnalysis, resolveConfiguration, BlockCompiler } from "@css-blocks/core";
22
import { BroccoliTreeImporter, EmberAnalysis, TEMPLATE_TYPE, pathToIdent } from "@css-blocks/ember-support";
33
import { TemplateIntegrationOptions } from "@opticss/template-api";
44
import mergeTrees = require("broccoli-merge-trees");
@@ -8,6 +8,8 @@ import type { PluginOptions } from "broccoli-plugin/dist/interfaces";
88
import debugGenerator from "debug";
99
import * as FSTree from "fs-tree-diff";
1010
import { Optimizer, postcss } from "opticss";
11+
import * as path from "path";
12+
import { unionInto } from "@opticss/util";
1113

1214
const debug = debugGenerator("css-blocks:ember-app");
1315

@@ -71,19 +73,8 @@ export class CSSBlocksApplicationPlugin extends Filter {
7173
mergeDeclarations: false,
7274
};
7375
let optimizer = new Optimizer(optimizerOptions, analyzer.optimizationOptions);
76+
let blocksUsed = new Set<Block>();
7477
for (let entry of entries) {
75-
let ident = pathToIdent(entry.relativePath);
76-
if (entry.relativePath.endsWith(".compiledblock.css")) {
77-
debug(`Parsing precompiled block: ${entry.relativePath}`);
78-
let block: Block;
79-
block = await factory.getBlock(ident);
80-
debug(`Got block: ${block.identifier}`);
81-
optimizer.addSource({
82-
filename: entry.relativePath,
83-
content: block.stylesheet!.toResult({to: entry.relativePath}),
84-
});
85-
blocks.push(block);
86-
}
8778
if (entry.relativePath.endsWith(".block-analysis.json")) {
8879
debug(`Processing analysis: ${entry.relativePath}`);
8980
let serializedAnalysis: SerializedSourceAnalysis<TEMPLATE_TYPE> = JSON.parse(this.input.readFileSync(entry.relativePath, "utf8"));
@@ -92,11 +83,39 @@ export class CSSBlocksApplicationPlugin extends Filter {
9283
serializedAnalysis.blocks[blockId] = pathToIdent(serializedAnalysis.blocks[blockId]);
9384
}
9485
let analysis = await EmberAnalysis.deserializeSource(serializedAnalysis, factory, analyzer);
86+
unionInto(blocksUsed, analysis.transitiveBlockDependencies());
9587
optimizer.addAnalysis(analysis.forOptimizer(config));
9688
}
9789
}
90+
let compiler = new BlockCompiler(postcss, config);
91+
for (let block of blocksUsed) {
92+
let content: postcss.Result;
93+
let filename = importer.debugIdentifier(block.identifier, config);
94+
if (block.precompiledStylesheet) {
95+
debug(`Optimizing precompiled stylesheet for ${filename}`);
96+
content = block.precompiledStylesheet.toResult();
97+
} else {
98+
debug(`Compiling stylesheet for optimization of ${filename}`);
99+
// XXX Do we need to worry about reservedClassnames here?
100+
content = compiler.compile(block, block.stylesheet!, new Set()).toResult();
101+
}
102+
optimizer.addSource({
103+
content,
104+
filename,
105+
});
106+
}
98107
debug(`Loaded ${blocks.length} blocks.`);
99108
debug(`Loaded ${optimizer.analyses.length} analyses.`);
109+
let cssFileName = `${this.appName}/styles/css-blocks.css`;
110+
let sourceMapFileName = `${this.appName}/styles/css-blocks.css.map`;
111+
let optLogFileName = `${this.appName}/styles/css-blocks.optimization.log`;
112+
let optimizationResult = await optimizer.optimize(cssFileName);
113+
debug(`Optimized CSS. There were ${optimizationResult.actions.performed.length} optimizations performed.`);
114+
this.output.mkdirSync(path.dirname(cssFileName), {recursive: true});
115+
this.output.writeFileSync(cssFileName, optimizationResult.output.content.toString(), "utf8");
116+
this.output.writeFileSync(sourceMapFileName, optimizationResult.output.sourceMap?.toString(), "utf8");
117+
this.output.writeFileSync(optLogFileName, optimizationResult.actions.logStrings().join("\n"), "utf8");
118+
debug("Wrote css, sourcemap, and optimization log.");
100119

101120
this.output.writeFileSync(
102121
`${this.appName}/services/-css-blocks-data.js`,

packages/@css-blocks/ember-app/src/index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import BroccoliDebug = require("broccoli-debug");
12
import funnel = require("broccoli-funnel");
23
import EmberApp from "ember-cli/lib/broccoli/ember-app";
34
import type Addon from "ember-cli/lib/models/addon";
@@ -130,7 +131,8 @@ const EMBER_ADDON: AddonImplementation<CSSBlocksApplicationAddon> = {
130131
if (type === "js") {
131132
if (env.isApp) {
132133
let appAndAddonTree = new CSSBlocksApplicationPlugin(env.modulePrefix, [env.app.addonTree(), tree], {});
133-
return funnel(appAndAddonTree, {srcDir: env.modulePrefix, destDir: env.modulePrefix});
134+
let debugTree = new BroccoliDebug(appAndAddonTree, `css-blocks:optimized`);
135+
return funnel(debugTree, {srcDir: env.modulePrefix, destDir: env.modulePrefix});
134136
} else {
135137
return tree;
136138
}

private-packages/fixtures-ember-v2/ember-app/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"@css-blocks-fixtures-v2/npm-based-blocks": "^1.0.0",
2626
"@css-blocks/ember": "^0.1.0",
2727
"@css-blocks/ember-app": "^0.1.0",
28+
"broccoli-debug": "^0.6.5",
2829
"ember-cli-babel": "^7.7.3",
2930
"ember-cli-htmlbars": "^5.2.0",
3031
"ember-engines": "^0.8.5"

0 commit comments

Comments
 (0)