diff --git a/src/index.js b/src/index.js index 0f11d62a..495fc920 100644 --- a/src/index.js +++ b/src/index.js @@ -15,6 +15,29 @@ function inferOption(option, defaultValue) { return option ? {} : defaultValue } +/** + * Recursivly get the correct import order from rollup + * We only process a file once + * + * @param {string} id + * @param {Function} getModuleInfo + * @param {Set} seen + */ +function getRecursiveImportOrder(id, getModuleInfo, seen = new Set()) { + if (seen.has(id)) { + return [] + } + + seen.add(id) + + const result = [id] + getModuleInfo(id).importedIds.forEach(importFile => { + result.push(...getRecursiveImportOrder(importFile, getModuleInfo, seen)) + }) + + return result +} + export default (options = {}) => { const filter = createFilter(options.include, options.exclude) const postcssPlugins = Array.isArray(options.plugins) ? @@ -149,10 +172,15 @@ export default (options = {}) => { const concat = new Concat(true, fileName, '\n') const entries = [...extracted.values()] - const { modules } = bundle[normalizePath(path.relative(dir, file))] + const { modules, facadeModuleId } = bundle[ + normalizePath(path.relative(dir, file)) + ] if (modules) { - const moduleIds = [...this.moduleIds] + const moduleIds = getRecursiveImportOrder( + facadeModuleId, + this.getModuleInfo + ) entries.sort( (a, b) => moduleIds.indexOf(a.id) - moduleIds.indexOf(b.id) ) diff --git a/test/__snapshots__/index.test.js.snap b/test/__snapshots__/index.test.js.snap index 47950e64..d6b4092a 100644 --- a/test/__snapshots__/index.test.js.snap +++ b/test/__snapshots__/index.test.js.snap @@ -195,6 +195,66 @@ console.log(undefined, undefined); " `; +exports[`extract nested: css code 1`] = ` +"body { + color: red; +} + +.bar-module_bar { + color: red; +} + +a { + font-weight: bold; +} + +.component-module_box { + color: blue; +} +/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZvby5jc3MiLCJiYXIubW9kdWxlLmNzcyIsIm5lc3RlZC5jc3MiLCJjb21wb25lbnQubW9kdWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLFVBQVU7QUFDWjs7QUNGQTtFQUNFLFVBQVU7QUFDWjs7QUNGQTtFQUNFLGlCQUFpQjtBQUNuQjs7QUNGQTtFQUNFLFdBQVc7QUFDYiIsImZpbGUiOiJidW5kbGUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiYm9keSB7XG4gIGNvbG9yOiByZWQ7XG59XG4iLCIuYmFyIHtcbiAgY29sb3I6IHJlZDtcbn1cbiIsImEge1xuICBmb250LXdlaWdodDogYm9sZDtcbn1cbiIsIi5ib3gge1xuICBjb2xvcjogYmx1ZTtcbn0iXX0=*/" +`; + +exports[`extract nested: js code 1`] = ` +"'use strict'; + +var bar = {\\"bar\\":\\"bar-module_bar\\"}; + +var component = {\\"box\\":\\"component-module_box\\"}; + +console.log(bar, component); +" +`; + +exports[`extract nested-delay-resolve: css code 1`] = ` +"body { + color: red; +} + +.bar-module_bar { + color: red; +} + +a { + font-weight: bold; +} + +.component-module_box { + color: blue; +} +/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZvby5jc3MiLCJiYXIubW9kdWxlLmNzcyIsIm5lc3RlZC5jc3MiLCJjb21wb25lbnQubW9kdWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLFVBQVU7QUFDWjs7QUNGQTtFQUNFLFVBQVU7QUFDWjs7QUNGQTtFQUNFLGlCQUFpQjtBQUNuQjs7QUNGQTtFQUNFLFdBQVc7QUFDYiIsImZpbGUiOiJidW5kbGUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiYm9keSB7XG4gIGNvbG9yOiByZWQ7XG59XG4iLCIuYmFyIHtcbiAgY29sb3I6IHJlZDtcbn1cbiIsImEge1xuICBmb250LXdlaWdodDogYm9sZDtcbn1cbiIsIi5ib3gge1xuICBjb2xvcjogYmx1ZTtcbn0iXX0=*/" +`; + +exports[`extract nested-delay-resolve: js code 1`] = ` +"'use strict'; + +var bar = {\\"bar\\":\\"bar-module_bar\\"}; + +var component = {\\"box\\":\\"component-module_box\\"}; + +console.log(bar, component); +" +`; + exports[`extract relative-path: css code 1`] = ` "body { color: red; diff --git a/test/fixtures/nested/bar.module.css b/test/fixtures/nested/bar.module.css new file mode 100644 index 00000000..9474f529 --- /dev/null +++ b/test/fixtures/nested/bar.module.css @@ -0,0 +1,3 @@ +.bar { + color: red; +} diff --git a/test/fixtures/nested/component.js b/test/fixtures/nested/component.js new file mode 100644 index 00000000..77e5072f --- /dev/null +++ b/test/fixtures/nested/component.js @@ -0,0 +1,3 @@ +import component from './component.module.css' + +export default component diff --git a/test/fixtures/nested/component.module.css b/test/fixtures/nested/component.module.css new file mode 100644 index 00000000..4adcaf2f --- /dev/null +++ b/test/fixtures/nested/component.module.css @@ -0,0 +1,3 @@ +.box { + color: blue; +} \ No newline at end of file diff --git a/test/fixtures/nested/foo.css b/test/fixtures/nested/foo.css new file mode 100644 index 00000000..60f1eab9 --- /dev/null +++ b/test/fixtures/nested/foo.css @@ -0,0 +1,3 @@ +body { + color: red; +} diff --git a/test/fixtures/nested/index.js b/test/fixtures/nested/index.js new file mode 100644 index 00000000..944a2051 --- /dev/null +++ b/test/fixtures/nested/index.js @@ -0,0 +1,6 @@ +import './foo.css' +import bar from './bar.module.css' +import './nested' +import component from './component' + +console.log(bar, component) diff --git a/test/fixtures/nested/nested.css b/test/fixtures/nested/nested.css new file mode 100644 index 00000000..0455b1ed --- /dev/null +++ b/test/fixtures/nested/nested.css @@ -0,0 +1,3 @@ +a { + font-weight: bold; +} diff --git a/test/fixtures/nested/nested.js b/test/fixtures/nested/nested.js new file mode 100644 index 00000000..6f50c34e --- /dev/null +++ b/test/fixtures/nested/nested.js @@ -0,0 +1,4 @@ +import './nested.css' + +export default 'test' +export { default as component } from './component' diff --git a/test/index.test.js b/test/index.test.js index a6bf49f8..658bda51 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -20,12 +20,33 @@ async function write({ outDir, options }) { + const { delayResolve, ...postCssOptions } = options + + let first = true + // Delay the resolving of the first css file + const lateResolve = { + name: 'late-resolve', + async resolveId(importee) { + // when it's not a css file and not the first css file we return + if (!first || !importee.endsWith('.css')) { + return null + } + + first = false + + // delay resolving + return new Promise(resolve => { + setTimeout(() => resolve(null), 1000) + }) + } + } + outDir = fixture('dist', outDir) const bundle = await rollup({ input: fixture(input), - plugins: [ - postcss(options) - ] + plugins: [postcss(postCssOptions), delayResolve && lateResolve].filter( + Boolean + ) }) await bundle.write({ format: 'cjs', @@ -295,6 +316,23 @@ snapshotMany('extract', [ sourceMap: 'inline', extract: true } + }, + { + title: 'nested', + input: 'nested/index.js', + options: { + sourceMap: 'inline', + extract: true + } + }, + { + title: 'nested-delay-resolve', + input: 'nested/index.js', + options: { + sourceMap: 'inline', + extract: true, + delayResolve: true + } } ])