Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/compiled-parcel-css-filename.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@compiled/parcel-optimizer': patch
---

Emit extracted Parcel optimizer stylesheets with a compiled-prefixed filename.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extract": true,
"inlineCss": false
}
11 changes: 11 additions & 0 deletions fixtures/parcel-optimizer-external-css-test-app/.parcelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": [
"@parcel/config-default"
],
"transformers": {
"*.{js,mjs,jsm,jsx,es6,cjs,ts,tsx}": ["@compiled/parcel-transformer", "..."]
},
"optimizers": {
"*.html": ["@compiled/parcel-optimizer", "..."]
}
}
110 changes: 110 additions & 0 deletions fixtures/parcel-optimizer-external-css-test-app/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# @compiled/parcel-optimizer-test-app

## 0.2.4

### Patch Changes

- Updated dependencies [bab22a2]
- Updated dependencies [f34e80d]
- @compiled/react@1.0.0

## 0.2.3

### Patch Changes

- Updated dependencies [60932d8]
- @compiled/react@0.22.0

## 0.2.2

### Patch Changes

- Updated dependencies [8e70033]
- @compiled/react@0.21.0

## 0.2.1

### Patch Changes

- Updated dependencies [6429bfe]
- @compiled/react@0.20.0

## 0.2.0

### Minor Changes

- 117eb47: Bump package dependencies to React 18 globally. Replace jsx and jsx-dev runtimes with modern syntax to circumvent `export \*` issues.

### Patch Changes

- Updated dependencies [117eb47]
- @compiled/react@0.19.0

## 0.1.6

### Patch Changes

- Updated dependencies [9a15e742]
- @compiled/react@0.18.0

## 0.1.5

### Patch Changes

- Updated dependencies [4b2e5eeb]
- Updated dependencies [39d9a02c]
- Updated dependencies [20528e91]
- Updated dependencies [5701b914]
- @compiled/react@0.17.0

## 0.1.4

### Patch Changes

- Updated dependencies [f8d01fa2]
- @compiled/react@0.16.0

## 0.1.3

### Patch Changes

- Updated dependencies [b6f3e41e]
- @compiled/react@0.15.0

## 0.1.2

### Patch Changes

- Updated dependencies [4a2174c5]
- Updated dependencies [c5377cdb]
- @compiled/react@0.14.0

## 0.1.1

### Patch Changes

- Updated dependencies [c4e6b7c0]
- Updated dependencies [c4e6b7c0]
- @compiled/react@0.13.0

## 0.1.0

### Minor Changes

- a41e41e6: Update monorepo node version to v18, and drop support for node v12

### Patch Changes

- Updated dependencies [a41e41e6]
- Updated dependencies [f9c957ef]
- @compiled/react@0.12.0

## 0.0.2

### Patch Changes

- 966a1080: Changed the approach of stylesheet extraction on Parcel

- @compiled/parcel-resolver is no longer used
- Pass styleRules to optimizer via metadata
- Optimizer then collects styleRules, and inserts it to output HTML

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions fixtures/parcel-optimizer-external-css-test-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "@compiled/parcel-optimizer-external-css-test-app",
"version": "0.2.4",
"private": true,
"dependencies": {
"@compiled/react": "^1.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@compiled/parcel-optimizer": "*",
"@parcel/config-default": "^2.8.3"
}
}
11 changes: 11 additions & 0 deletions fixtures/parcel-optimizer-external-css-test-app/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="root"></div>
<script type="module" src="./index.jsx"></script>
</body>
</html>
65 changes: 65 additions & 0 deletions fixtures/parcel-optimizer-external-css-test-app/src/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// eslint-disable-next-line import/named -- cssMapScoped is not in public types
import { styled, cssMapScoped } from '@compiled/react';
import * as React from 'react';

const ComponentA = styled.div({
color: 'red',
':hover': {
color: 'green',
},
':focus': {
color: 'orange',
},
});

const ComponentB = styled.div({
'@media screen': {
color: 'red',
},
});

const ComponentC = styled.div({
'@media (min-width: 500px)': {
border: '2px solid red',
},
});

const ComponentD = styled.div({
'@media (min-width: 500px)': {
border: '2px solid red',
content: 'large screen',
},
});

// @ts-expect-error -- cssMapScoped is not in public types
const baseStyles = cssMapScoped({
default: {
'.editor .panel': { backgroundColor: 'gray', padding: '8px' },
},
});

// @ts-expect-error -- cssMapScoped is not in public types
const overrideStyles = cssMapScoped({
default: {
'.editor .panel': { backgroundColor: 'pink' },
},
});

const App = () => (
<>
<ComponentA />
<ComponentB />
<ComponentC />
<ComponentD />
<div css={baseStyles.default}>
<div className="editor">
<div className="panel" />
</div>
</div>
<div css={[baseStyles.default, overrideStyles.default]}>
<div className="editor">
<div className="panel" />
</div>
</div>
</>
);
147 changes: 84 additions & 63 deletions packages/parcel-optimizer/src/__tests__/optimizer.parceltest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,84 +9,105 @@ import { MemoryFS } from '@parcel/fs';
import { format } from 'prettier';

const rootPath = join(__dirname, '..', '..', '..', '..');
const fixtureRoot = join(rootPath, 'fixtures/parcel-optimizer-test-app');
const inlineCssFixtureRoot = join(rootPath, 'fixtures/parcel-optimizer-test-app');
const externalCssFixtureRoot = join(rootPath, 'fixtures/parcel-optimizer-external-css-test-app');

const workerFarm = createWorkerFarm();
const outputFS = new MemoryFS(workerFarm);

const parcel = new Parcel({
config: join(fixtureRoot, '.parcelrc'),
entries: [join(fixtureRoot, 'src', 'index.html')],
outputFS,
targets: {
default: {
distDir: join(fixtureRoot, 'dist'),
const runParcel = async (fixtureRoot: string) => {
const parcel = new Parcel({
config: join(fixtureRoot, '.parcelrc'),
entries: [join(fixtureRoot, 'src', 'index.html')],
outputFS,
targets: {
default: {
distDir: join(fixtureRoot, 'dist'),
},
},
},
workerFarm,
mode: 'production',
});
workerFarm,
mode: 'production',
});

const { changedAssets, bundleGraph } = await parcel.run();

const asset = Array.from(changedAssets.values()).find(
(asset) => asset.filePath === join(fixtureRoot, '/src/index.html')
);

return outputFS.readFile(bundleGraph.getBundlesWithAsset(asset!)[0].filePath, 'utf8');
};

const expectSortedCss = (css: string) => {
expect(
format(css, {
parser: 'css',
singleQuote: true,
})
).toMatchInlineSnapshot(`
".cc-97o8ng .editor .panel {
background-color: gray;
padding-top: 8px;
padding-right: 8px;
padding-bottom: 8px;
padding-left: 8px;
}
.cc-9z735k .editor .panel {
background-color: pink;
}
._syaz5scu {
color: red;
}
._f8pjruxl:focus {
color: orange;
}
._30l3bf54:hover {
color: green;
}
@media screen {
._43475scu {
color: red;
}
}
@media (min-width: 500px) {
._171dak0l {
border: 2px solid red;
}
._14yn1439 {
content: 'large screen';
}
}
"
`);
};

afterAll(() => {
workerFarm.end();
});

describe('optimizer', () => {
it('sorts css rules', async () => {
const { changedAssets, bundleGraph } = await parcel.run();

const asset = Array.from(changedAssets.values()).find(
(asset) => asset.filePath === join(fixtureRoot, '/src/index.html')
);

const outputHtml = await outputFS.readFile(
bundleGraph.getBundlesWithAsset(asset!)[0].filePath,
'utf8'
);
it('sorts inline css rules', async () => {
const outputHtml = await runParcel(inlineCssFixtureRoot);

const css = /<style>(.*?)<\/style>/.exec(outputHtml)?.pop();

if (!css) throw new Error('No CSS is found.');

expect(
format(css, {
parser: 'css',
singleQuote: true,
})
).toMatchInlineSnapshot(`
".cc-97o8ng .editor .panel {
background-color: gray;
padding-top: 8px;
padding-right: 8px;
padding-bottom: 8px;
padding-left: 8px;
}
.cc-9z735k .editor .panel {
background-color: pink;
}
._syaz5scu {
color: red;
}
._f8pjruxl:focus {
color: orange;
}
._30l3bf54:hover {
color: green;
}
@media screen {
._43475scu {
color: red;
}
}
@media (min-width: 500px) {
._171dak0l {
border: 2px solid red;
}
._14yn1439 {
content: 'large screen';
}
}
"
`);
expectSortedCss(css);
}, 30000);

it('emits extracted css with a compiled-prefixed filename', async () => {
const outputHtml = await runParcel(externalCssFixtureRoot);

const cssFileName = /<link[^>]+href="\/?(compiled\.[^"]+\.css)"[^>]*>/.exec(outputHtml)?.pop();

if (!cssFileName) throw new Error('No compiled CSS link is found.');

expect(cssFileName).toMatch(/^compiled\.[a-z0-9]+\.css$/);

const css = await outputFS.readFile(join(externalCssFixtureRoot, 'dist', cssFileName), 'utf8');

expect(css).toContain('background-color:gray');
expect(css).toContain('color:red');
}, 30000);
});
Loading
Loading