@compiled/parcel-optimizer 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -1
- package/dist/index.js +74 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +8 -4
- package/src/__tests__/optimizer.parceltest.ts +22 -15
- package/src/index.ts +103 -3
- package/src/types.ts +7 -0
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,10 +1,82 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const assert_1 = __importDefault(require("assert"));
|
|
7
|
+
const path_1 = require("path");
|
|
3
8
|
const css_1 = require("@compiled/css");
|
|
9
|
+
const utils_1 = require("@compiled/utils");
|
|
4
10
|
const plugin_1 = require("@parcel/plugin");
|
|
11
|
+
const posthtml_1 = __importDefault(require("posthtml"));
|
|
12
|
+
const posthtml_insert_at_1 = require("posthtml-insert-at");
|
|
13
|
+
const configFiles = [
|
|
14
|
+
'.compiledcssrc',
|
|
15
|
+
'.compiledcssrc.json',
|
|
16
|
+
'compiledcss.js',
|
|
17
|
+
'compiledcss.config.js',
|
|
18
|
+
];
|
|
5
19
|
exports.default = new plugin_1.Optimizer({
|
|
6
|
-
async
|
|
7
|
-
|
|
20
|
+
async loadConfig({ config, options }) {
|
|
21
|
+
const conf = await config.getConfigFrom((0, path_1.join)(options.projectRoot, 'index'), configFiles, {
|
|
22
|
+
packageKey: '@compiled/parcel-optimizer',
|
|
23
|
+
});
|
|
24
|
+
const contents = {
|
|
25
|
+
inlineCss: false,
|
|
26
|
+
};
|
|
27
|
+
if (conf) {
|
|
28
|
+
config.invalidateOnStartup();
|
|
29
|
+
Object.assign(contents, conf.contents);
|
|
30
|
+
}
|
|
31
|
+
return contents;
|
|
32
|
+
},
|
|
33
|
+
async optimize({ contents, map, bundle, bundleGraph, options, config }) {
|
|
34
|
+
const { outputFS } = options;
|
|
35
|
+
const styleRules = new Set();
|
|
36
|
+
// Traverse the descendants of HTML bundle
|
|
37
|
+
// Extract the stylesRules from assets
|
|
38
|
+
bundleGraph.traverseBundles((childBundle) => {
|
|
39
|
+
childBundle.traverseAssets((asset) => {
|
|
40
|
+
const rules = asset.meta.styleRules;
|
|
41
|
+
if (rules == null) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
(0, assert_1.default)(rules instanceof Array);
|
|
45
|
+
for (const rule of rules) {
|
|
46
|
+
styleRules.add(rule);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}, bundle);
|
|
50
|
+
if (styleRules.size === 0)
|
|
51
|
+
return { contents, map };
|
|
52
|
+
const stylesheet = (0, css_1.sort)(Array.from(styleRules).join(''));
|
|
53
|
+
let newContents = '';
|
|
54
|
+
if (config.inlineCss) {
|
|
55
|
+
newContents = (await (0, posthtml_1.default)()
|
|
56
|
+
.use((0, posthtml_insert_at_1.insertAt)({
|
|
57
|
+
selector: 'head',
|
|
58
|
+
append: '<style>' + stylesheet + '</style>',
|
|
59
|
+
behavior: 'inside',
|
|
60
|
+
}))
|
|
61
|
+
.process(contents.toString())).html;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const { distDir } = bundle.target;
|
|
65
|
+
if (!outputFS.existsSync(distDir)) {
|
|
66
|
+
await outputFS.mkdirp(distDir);
|
|
67
|
+
}
|
|
68
|
+
const cssFileName = (0, path_1.basename)(bundle.displayName, '.html') + '.' + (0, utils_1.hash)(stylesheet) + '.css';
|
|
69
|
+
await outputFS.writeFile((0, path_1.join)(distDir, cssFileName), stylesheet, undefined // for TypeScript
|
|
70
|
+
);
|
|
71
|
+
newContents = (await (0, posthtml_1.default)()
|
|
72
|
+
.use((0, posthtml_insert_at_1.insertAt)({
|
|
73
|
+
selector: 'head',
|
|
74
|
+
append: '<link href="' + bundle.target.publicUrl + cssFileName + '" rel="stylesheet" />',
|
|
75
|
+
behavior: 'inside',
|
|
76
|
+
}))
|
|
77
|
+
.process(contents.toString())).html;
|
|
78
|
+
}
|
|
79
|
+
return { contents: newContents, map };
|
|
8
80
|
},
|
|
9
81
|
});
|
|
10
82
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@compiled/parcel-optimizer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "A familiar and performant compile time CSS-in-JS library for React.",
|
|
5
5
|
"bugs": "https://github.com/atlassian-labs/compiled/issues/new?assignees=&labels=bug&template=bug_report.md",
|
|
6
6
|
"repository": {
|
|
@@ -20,14 +20,18 @@
|
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@compiled/css": "^0.8.1",
|
|
23
|
-
"@
|
|
23
|
+
"@compiled/utils": "^0.6.16",
|
|
24
|
+
"@parcel/plugin": "^2.3.1",
|
|
25
|
+
"posthtml": "^0.16.6",
|
|
26
|
+
"posthtml-insert-at": "^0.2.7"
|
|
24
27
|
},
|
|
25
28
|
"devDependencies": {
|
|
26
29
|
"@parcel/core": "^2.3.1",
|
|
27
30
|
"@parcel/fs": "^2.3.1",
|
|
28
31
|
"@parcel/types": "^2.3.1",
|
|
29
|
-
"
|
|
30
|
-
"
|
|
32
|
+
"prettier": "^2.8.1",
|
|
33
|
+
"ts-node": "^10.8.2",
|
|
34
|
+
"tsconfig-paths": "^3.14.1"
|
|
31
35
|
},
|
|
32
36
|
"engines": {
|
|
33
37
|
"parcel": "^2.0.0"
|
|
@@ -6,6 +6,7 @@ import { join } from 'path';
|
|
|
6
6
|
|
|
7
7
|
import Parcel, { createWorkerFarm } from '@parcel/core';
|
|
8
8
|
import { MemoryFS } from '@parcel/fs';
|
|
9
|
+
import { format } from 'prettier';
|
|
9
10
|
|
|
10
11
|
const rootPath = join(__dirname, '..', '..', '..', '..');
|
|
11
12
|
const fixtureRoot = join(rootPath, 'fixtures/parcel-optimizer-test-app');
|
|
@@ -23,6 +24,7 @@ const parcel = new Parcel({
|
|
|
23
24
|
},
|
|
24
25
|
},
|
|
25
26
|
workerFarm,
|
|
27
|
+
mode: 'production',
|
|
26
28
|
});
|
|
27
29
|
|
|
28
30
|
afterAll(() => {
|
|
@@ -32,40 +34,45 @@ afterAll(() => {
|
|
|
32
34
|
describe('optimizer', () => {
|
|
33
35
|
it('sorts css rules', async () => {
|
|
34
36
|
const { changedAssets, bundleGraph } = await parcel.run();
|
|
37
|
+
|
|
35
38
|
const asset = Array.from(changedAssets.values()).find(
|
|
36
|
-
(asset) => asset.filePath === join(fixtureRoot, '/src/
|
|
39
|
+
(asset) => asset.filePath === join(fixtureRoot, '/src/index.html')
|
|
37
40
|
);
|
|
38
41
|
|
|
39
|
-
const
|
|
42
|
+
const outputHtml = await outputFS.readFile(
|
|
40
43
|
bundleGraph.getBundlesWithAsset(asset!)[0].filePath,
|
|
41
44
|
'utf8'
|
|
42
45
|
);
|
|
43
|
-
expect(outputCss).toMatchInlineSnapshot(`
|
|
44
|
-
"
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
const css = /<style>(.*?)<\/style>/.exec(outputHtml)?.pop();
|
|
48
|
+
|
|
49
|
+
if (!css) throw new Error('No CSS is found.');
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
expect(
|
|
52
|
+
format(css, {
|
|
53
|
+
parser: 'css',
|
|
54
|
+
singleQuote: true,
|
|
55
|
+
})
|
|
56
|
+
).toMatchInlineSnapshot(`
|
|
57
|
+
"._syaz5scu {
|
|
58
|
+
color: red;
|
|
59
|
+
}
|
|
60
|
+
._f8pjruxl:focus {
|
|
51
61
|
color: orange;
|
|
52
62
|
}
|
|
53
|
-
|
|
54
|
-
.color-blue:hover {
|
|
63
|
+
._30l3bf54:hover {
|
|
55
64
|
color: green;
|
|
56
65
|
}
|
|
57
|
-
|
|
58
66
|
@media screen {
|
|
59
|
-
.
|
|
67
|
+
._43475scu {
|
|
60
68
|
color: red;
|
|
61
69
|
}
|
|
62
70
|
}
|
|
63
|
-
|
|
64
71
|
@media (min-width: 500px) {
|
|
65
|
-
.
|
|
72
|
+
._171dak0l {
|
|
66
73
|
border: 2px solid red;
|
|
67
74
|
}
|
|
68
|
-
.
|
|
75
|
+
._14yn1439 {
|
|
69
76
|
content: 'large screen';
|
|
70
77
|
}
|
|
71
78
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,108 @@
|
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import { join, basename } from 'path';
|
|
3
|
+
|
|
1
4
|
import { sort } from '@compiled/css';
|
|
5
|
+
import { hash } from '@compiled/utils';
|
|
2
6
|
import { Optimizer } from '@parcel/plugin';
|
|
7
|
+
import posthtml from 'posthtml';
|
|
8
|
+
import { insertAt } from 'posthtml-insert-at';
|
|
9
|
+
|
|
10
|
+
import type { ParcelOptimizerOpts } from './types';
|
|
11
|
+
|
|
12
|
+
const configFiles = [
|
|
13
|
+
'.compiledcssrc',
|
|
14
|
+
'.compiledcssrc.json',
|
|
15
|
+
'compiledcss.js',
|
|
16
|
+
'compiledcss.config.js',
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export default new Optimizer<ParcelOptimizerOpts>({
|
|
20
|
+
async loadConfig({ config, options }) {
|
|
21
|
+
const conf = await config.getConfigFrom(join(options.projectRoot, 'index'), configFiles, {
|
|
22
|
+
packageKey: '@compiled/parcel-optimizer',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const contents = {
|
|
26
|
+
inlineCss: false,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
if (conf) {
|
|
30
|
+
config.invalidateOnStartup();
|
|
31
|
+
Object.assign(contents, conf.contents);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return contents;
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
async optimize({ contents, map, bundle, bundleGraph, options, config }) {
|
|
38
|
+
const { outputFS } = options;
|
|
39
|
+
|
|
40
|
+
const styleRules = new Set<string>();
|
|
41
|
+
|
|
42
|
+
// Traverse the descendants of HTML bundle
|
|
43
|
+
// Extract the stylesRules from assets
|
|
44
|
+
bundleGraph.traverseBundles((childBundle) => {
|
|
45
|
+
childBundle.traverseAssets((asset) => {
|
|
46
|
+
const rules = asset.meta.styleRules;
|
|
47
|
+
if (rules == null) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
assert(rules instanceof Array);
|
|
52
|
+
|
|
53
|
+
for (const rule of rules) {
|
|
54
|
+
styleRules.add(rule as string);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}, bundle);
|
|
58
|
+
|
|
59
|
+
if (styleRules.size === 0) return { contents, map };
|
|
60
|
+
|
|
61
|
+
const stylesheet = sort(Array.from(styleRules).join(''));
|
|
62
|
+
|
|
63
|
+
let newContents = '';
|
|
64
|
+
|
|
65
|
+
if (config.inlineCss) {
|
|
66
|
+
newContents = (
|
|
67
|
+
await posthtml()
|
|
68
|
+
.use(
|
|
69
|
+
insertAt({
|
|
70
|
+
selector: 'head',
|
|
71
|
+
append: '<style>' + stylesheet + '</style>',
|
|
72
|
+
behavior: 'inside',
|
|
73
|
+
})
|
|
74
|
+
)
|
|
75
|
+
.process(contents.toString())
|
|
76
|
+
).html;
|
|
77
|
+
} else {
|
|
78
|
+
const { distDir } = bundle.target;
|
|
79
|
+
|
|
80
|
+
if (!outputFS.existsSync(distDir)) {
|
|
81
|
+
await outputFS.mkdirp(distDir);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const cssFileName = basename(bundle.displayName, '.html') + '.' + hash(stylesheet) + '.css';
|
|
85
|
+
|
|
86
|
+
await outputFS.writeFile(
|
|
87
|
+
join(distDir, cssFileName),
|
|
88
|
+
stylesheet,
|
|
89
|
+
undefined // for TypeScript
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
newContents = (
|
|
93
|
+
await posthtml()
|
|
94
|
+
.use(
|
|
95
|
+
insertAt({
|
|
96
|
+
selector: 'head',
|
|
97
|
+
append:
|
|
98
|
+
'<link href="' + bundle.target.publicUrl + cssFileName + '" rel="stylesheet" />',
|
|
99
|
+
behavior: 'inside',
|
|
100
|
+
})
|
|
101
|
+
)
|
|
102
|
+
.process(contents.toString())
|
|
103
|
+
).html;
|
|
104
|
+
}
|
|
3
105
|
|
|
4
|
-
|
|
5
|
-
async optimize({ contents, map }) {
|
|
6
|
-
return { contents: sort(contents.toString()), map };
|
|
106
|
+
return { contents: newContents, map };
|
|
7
107
|
},
|
|
8
108
|
});
|