Skip to content

Commit

Permalink
improve CSS module support (#1666)
Browse files Browse the repository at this point in the history
  • Loading branch information
FredKSchott committed Nov 26, 2020
1 parent cd3027f commit 5b7ce4d
Show file tree
Hide file tree
Showing 9 changed files with 222 additions and 109 deletions.
3 changes: 2 additions & 1 deletion snowpack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
"chokidar": "^3.4.0",
"compressible": "^2.0.18",
"cosmiconfig": "^7.0.0",
"css-modules-loader-core": "^1.1.0",
"deepmerge": "^4.2.2",
"detect-port": "^1.3.0",
"es-module-lexer": "^0.3.24",
Expand All @@ -79,6 +78,8 @@
"npm-run-path": "^4.0.1",
"open": "^7.0.4",
"p-queue": "^6.6.1",
"postcss": "^8.1.8",
"postcss-modules": "^3.2.2",
"resolve-from": "^5.0.0",
"rimraf": "^3.0.0",
"signal-exit": "^3.0.3",
Expand Down
49 changes: 37 additions & 12 deletions snowpack/src/build/build-import-proxy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type CSSModuleLoader from 'css-modules-loader-core';
import type {Postcss} from 'postcss';
import path from 'path';
import {readFileSync} from 'fs';
import {SnowpackConfig} from '../types/snowpack';
Expand Down Expand Up @@ -155,7 +155,8 @@ if (typeof document !== 'undefined') {${
return wrapImportMeta({code: cssImportProxyCode, hmr, env: false, config});
}

let _cssModuleLoader: CSSModuleLoader;
let _postCss: Postcss;
let _postCssModules: any;
async function generateCssModuleImportProxy({
url,
code,
Expand All @@ -167,27 +168,45 @@ async function generateCssModuleImportProxy({
hmr: boolean;
config: SnowpackConfig;
}) {
_cssModuleLoader = _cssModuleLoader || new (require('css-modules-loader-core'))();
const {injectableSource, exportTokens} = await _cssModuleLoader.load(code, url, undefined, () => {
throw new Error('Imports in CSS Modules are not yet supported.');
_postCss = _postCss || require('postcss');
_postCssModules = _postCssModules || require('postcss-modules');
let moduleJson: string | undefined;
const processor = _postCss([
_postCssModules({
getJSON: (_, json) => {
moduleJson = json;
},
}),
]);
const result = await processor.process(code, {
from: url,
to: url + '.proxy.js',
});
// log any warnings that happened.
result
.warnings()
.forEach((element) => logger.warn(`${url} - ${element.text}`, {name: 'snowpack:cssmodules'}));
// return the JS+CSS proxy file.
return `
export let code = ${JSON.stringify(injectableSource)};
let json = ${JSON.stringify(exportTokens)};
export let code = ${JSON.stringify(result.css)};
let json = ${JSON.stringify(moduleJson)};
export default json;
${
hmr
? `
hmr
? `
import * as __SNOWPACK_HMR_API__ from '${getMetaUrlPath('hmr-client.js', config)}';
import.meta.hot = __SNOWPACK_HMR_API__.createHotContext(import.meta.url);\n` : ``}
import.meta.hot = __SNOWPACK_HMR_API__.createHotContext(import.meta.url);\n`
: ``
}
// [snowpack] add styles to the page (skip if no document exists)
if (typeof document !== 'undefined') {${
hmr
? `
import.meta.hot.dispose(() => {
document && document.head.removeChild(styleEl);
});\n`
: ``}
: ``
}
const styleEl = document.createElement("style");
const codeEl = document.createTextNode(code);
styleEl.type = 'text/css';
Expand Down Expand Up @@ -231,7 +250,13 @@ export async function wrapImportProxy({
return generateDefaultImportProxy(url);
}

export function generateEnvModule({mode, isSSR}: {mode: 'development' | 'production', isSSR: boolean}) {
export function generateEnvModule({
mode,
isSSR,
}: {
mode: 'development' | 'production';
isSSR: boolean;
}) {
const envObject: Record<string, string | boolean | undefined> = getSnowpackPublicEnvVariables();
envObject.MODE = mode;
envObject.NODE_ENV = mode;
Expand Down
76 changes: 76 additions & 0 deletions test/build/css-modules/__snapshots__
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`snowpack build css-modules: allFiles 1`] = `
Array [
"__snowpack__/env.js",
"src/App.js",
"src/App.module.css",
"src/App.module.css.proxy.js",
]
`;

exports[`snowpack build css-modules: build/__snowpack__/env.js 1`] = `"export default {\\"MODE\\":\\"production\\",\\"NODE_ENV\\":\\"production\\",\\"SSR\\":false};"`;

exports[`snowpack build css-modules: build/src/App.js 1`] = `
"import foo from \\"./App.module.css.proxy.js\\";
console.log(foo);"
`;

exports[`snowpack build css-modules: build/src/App.module.css 1`] = `
".App {
text-align: center;
}
.App code {
background: #FFF3;
padding: 4px 8px;
border-radius: 4px;
}
.App p {
margin: 0.4rem;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}"
`;

exports[`snowpack build css-modules: build/src/App.module.css.proxy.js 1`] = `
"
export let code = \\"._App_10m0p_1 { text-align: center;}._App_10m0p_1 code { background: #FFF3; padding: 4px 8px; border-radius: 4px;}._App_10m0p_1 p { margin: 0.4rem;}._App-logo_10m0p_12 { height: 40vmin; pointer-events: none;}@media (prefers-reduced-motion: no-preference) { ._App-logo_10m0p_12 { animation: _App-logo-spin_10m0p_1 infinite 20s linear; }}._App-header_10m0p_23 { background-color: #282c34; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: calc(10px + 2vmin); color: white;}._App-link_10m0p_34 { color: #61dafb;}@keyframes _App-logo-spin_10m0p_1 { from { transform: rotate(0deg); } to { transform: rotate(360deg); }}\\";
let json = {\\"App\\":\\"_App_10m0p_1\\",\\"App-logo\\":\\"_App-logo_10m0p_12\\",\\"App-logo-spin\\":\\"_App-logo-spin_10m0p_1\\",\\"App-header\\":\\"_App-header_10m0p_23\\",\\"App-link\\":\\"_App-link_10m0p_34\\"};
export default json;
// [snowpack] add styles to the page (skip if no document exists)
if (typeof document !== 'undefined') {
const styleEl = document.createElement(\\"style\\");
const codeEl = document.createTextNode(code);
styleEl.type = 'text/css';
styleEl.appendChild(codeEl);
document.head.appendChild(styleEl);
}"
`;
22 changes: 22 additions & 0 deletions test/build/css-modules/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"private": true,
"version": "1.0.1",
"name": "@snowpack/test-css-modules",
"description": "Tests CSS Module support",
"scripts": {
"testbuild": "snowpack build"
},
"snowpack": {
"mount": {
"./src": "/src"
}
},
"dependencies": {
"water.css": "^2.0.0"
},
"devDependencies": {
"@snowpack/plugin-optimize": "^0.2.6",
"@snowpack/plugin-sass": "^1.1.1",
"snowpack": "^2.14.3"
}
}
2 changes: 2 additions & 0 deletions test/build/css-modules/src/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import foo from './App.module.css';
console.log(foo);
45 changes: 45 additions & 0 deletions test/build/css-modules/src/App.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.App {
text-align: center;
}
.App code {
background: #FFF3;
padding: 4px 8px;
border-radius: 4px;
}
.App p {
margin: 0.4rem;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}

.App-link {
color: #61dafb;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
14 changes: 7 additions & 7 deletions test/build/preload-css/__snapshots__

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -14569,8 +14569,8 @@ exports[`create-snowpack-app app-template-vue-typescript > build: _dist_/compone

exports[`create-snowpack-app app-template-vue-typescript > build: _dist_/components/Bar.module.css.proxy.js 1`] = `
"
export let code = \\"._dist_components_Bar_module__bar-jsx { color: red;}\\";
let json = {\\"bar-jsx\\":\\"_dist_components_Bar_module__bar-jsx\\"};
export let code = \\"._bar-jsx_1ih6s_1 { color: red;}\\";
let json = {\\"bar-jsx\\":\\"_bar-jsx_1ih6s_1\\"};
export default json;
// [snowpack] add styles to the page (skip if no document exists)
if (typeof document !== 'undefined') {
Expand Down Expand Up @@ -14659,8 +14659,8 @@ exports[`create-snowpack-app app-template-vue-typescript > build: _dist_/compone

exports[`create-snowpack-app app-template-vue-typescript > build: _dist_/components/Foo.module.css.proxy.js 1`] = `
"
export let code = \\"._dist_components_Foo_module__foo-tsx { color: green;}\\";
let json = {\\"foo-tsx\\":\\"_dist_components_Foo_module__foo-tsx\\"};
export let code = \\"._foo-tsx_kh4bk_1 { color: green;}\\";
let json = {\\"foo-tsx\\":\\"_foo-tsx_kh4bk_1\\"};
export default json;
// [snowpack] add styles to the page (skip if no document exists)
if (typeof document !== 'undefined') {
Expand Down

0 comments on commit 5b7ce4d

Please sign in to comment.