Skip to content

Commit c6ac1fd

Browse files
author
Tim Lindvall
committedAug 1, 2020
feat: Optimized css in ember-app build output.
1 parent a825a16 commit c6ac1fd

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed
 

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

+29
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { unionInto } from "@opticss/util";
55
import mergeTrees = require("broccoli-merge-trees");
66
import type { InputNode } from "broccoli-node-api";
77
import Filter = require("broccoli-persistent-filter");
8+
import Plugin = require("broccoli-plugin");
89
import type { PluginOptions } from "broccoli-plugin/dist/interfaces";
910
import debugGenerator from "debug";
1011
import * as FSTree from "fs-tree-diff";
@@ -123,3 +124,31 @@ export class CSSBlocksApplicationPlugin extends Filter {
123124
`);
124125
}
125126
}
127+
128+
/**
129+
* A plugin that is used during the CSS preprocess step to merge in the CSS Blocks optimized content
130+
* with application styles and the existing css tree.
131+
*
132+
* This plugin expects two broccoli nodes, in the following order...
133+
* 1) The result of the CSSBlocksApplicationPlugin.
134+
* 2) The css tree, passed in to `preprocessTree()`.
135+
*
136+
* The result of this plugin will be a file in app/styles/app.css that includes existing content appended
137+
* with the contents of css-blocks.css. This should be merged with the existing css tree to overwrite
138+
* the app.css file with this one.
139+
*/
140+
export class CSSBlocksStylesProcessorPlugin extends Plugin {
141+
async build() {
142+
// Read the optimized CSS Blocks styles file, generated previously by the CSSBlocksApplicationPlugin.
143+
// There should only be one css-blocks.css file.
144+
const blocksFileEntry = this.input.at(0).entries(".", {globs: ["**/css-blocks.css"]})[0];
145+
146+
// And read the application CSS that was previously built by Ember and ignored by CSS Blocks.
147+
const blocksFileContents = this.input.at(0).readFileSync(blocksFileEntry.relativePath, { encoding: "utf8" });
148+
const appCssFileContents = this.input.at(1).readFileSync("app/styles/app.css", { encoding: "utf8" });
149+
150+
// Now, write out the combined result of the application CSS and CSS Blocks contents.
151+
this.output.mkdirSync("app/styles", { recursive: true });
152+
this.output.writeFileSync("app/styles/app.css", `${appCssFileContents}${blocksFileContents}`);
153+
}
154+
}

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

+25-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import BroccoliDebug = require("broccoli-debug");
22
import funnel = require("broccoli-funnel");
3+
import mergeTrees = require("broccoli-merge-trees");
34
import EmberApp from "ember-cli/lib/broccoli/ember-app";
45
import type Addon from "ember-cli/lib/models/addon";
56
import type { AddonImplementation, ThisAddon } from "ember-cli/lib/models/addon";
67
import Project from "ember-cli/lib/models/project";
78

8-
import { CSSBlocksApplicationPlugin } from "./brocolli-plugin";
9+
import { CSSBlocksApplicationPlugin, CSSBlocksStylesProcessorPlugin } from "./brocolli-plugin";
910

1011
interface AddonEnvironment {
1112
parent: Addon | EmberApp;
@@ -19,6 +20,7 @@ interface CSSBlocksApplicationAddon {
1920
_modulePrefix(): string;
2021
env: AddonEnvironment | undefined;
2122
getEnv(parent): AddonEnvironment;
23+
broccoliAppPluginInstance: CSSBlocksApplicationPlugin | undefined;
2224
}
2325

2426
/**
@@ -60,6 +62,12 @@ const EMBER_ADDON: AddonImplementation<CSSBlocksApplicationAddon> = {
6062

6163
env: undefined,
6264

65+
/**
66+
* The instance of the CSSBlocksApplicationPlugin. This instance is
67+
* generated during the JS tree and is needed for the CSS tree.
68+
*/
69+
broccoliAppPluginInstance: undefined,
70+
6371
/**
6472
* Initalizes this addon instance for use.
6573
* @param parent - The project or addon that directly depends on this addon.
@@ -128,14 +136,28 @@ const EMBER_ADDON: AddonImplementation<CSSBlocksApplicationAddon> = {
128136
preprocessTree(type, tree) {
129137
// tslint:disable-next-line:prefer-unknown-to-any
130138
let env = this.env!;
139+
131140
if (type === "js") {
132141
if (env.isApp) {
133-
let appAndAddonTree = new CSSBlocksApplicationPlugin(env.modulePrefix, [env.app.addonTree(), tree], {});
134-
let debugTree = new BroccoliDebug(appAndAddonTree, `css-blocks:optimized`);
142+
this.broccoliAppPluginInstance = new CSSBlocksApplicationPlugin(env.modulePrefix, [env.app.addonTree(), tree], {});
143+
let debugTree = new BroccoliDebug(this.broccoliAppPluginInstance, `css-blocks:optimized`);
135144
return funnel(debugTree, {srcDir: env.modulePrefix, destDir: env.modulePrefix});
136145
} else {
137146
return tree;
138147
}
148+
} else if (type === "css") {
149+
// We can't do much if we don't have the result from CSSBlocksApplicationPlugin.
150+
// This should never happen because the JS tree is processed before the CSS tree,
151+
// but just in case....
152+
if (!env.isApp) {
153+
return tree;
154+
}
155+
if (!this.broccoliAppPluginInstance) {
156+
throw new Error("[css-blocks/ember-app] The CSS tree ran before the JS tree, so the CSS tree doesn't have the contents for CSS Blocks files. This shouldn't ever happen, but if it does, please file an issue with us!");
157+
}
158+
// Get the combined CSS file
159+
const cssBlocksContentsTree = new CSSBlocksStylesProcessorPlugin([this.broccoliAppPluginInstance, tree]);
160+
return new BroccoliDebug(mergeTrees([tree, cssBlocksContentsTree], { overwrite: true }), "css-blocks:css-preprocess");
139161
} else {
140162
return tree;
141163
}

0 commit comments

Comments
 (0)
Please sign in to comment.