Skip to content
Permalink
Browse files

feat: rollup transform dependencies support (#438)

  • Loading branch information...
tivac committed Jun 26, 2018
1 parent 4afe3af commit 7347d8f766bfda44288b7cb59a3cc9dba06a293f
@@ -6,4 +6,4 @@ node_modules/
parsers/
results/
specimens/
specimens/output/
output/

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -22,7 +22,7 @@
"watch": "jest --watch"
},
"devDependencies": {
"@tivac/eslint-config": "^2.2.0",
"@tivac/eslint-config": "^2.2.1",
"browserify": "^16.2.0",
"cli-tester": "^2.0.0",
"cssnano": "^4.0.0-rc.1",
@@ -34,29 +34,19 @@
"from2-string": "^1.1.0",
"husky": "^0.14.3",
"jest": "^23.1.0",
"jest-cli": "^23.1.0",
"lerna": "^3.0.0-beta.21",
"lint-staged": "^7.0.4",
"modular-css-core": "file:./packages/core",
"pegjs": "^0.10.0",
"rollup": "^0.60.4",
"rollup": "^0.61.2",
"rollup-plugin-svelte": "^4.1.0",
"shelljs": "^0.8.1",
"svelte": "^2.8.1",
"test-utils": "file:./packages/test-utils",
"watchify": "^3.9.0",
"webpack": "^4.12.1"
},
"jest": {
"coveragePathIgnorePatterns": [
"node_modules",
"parsers",
"test-utils"
],
"watchPathIgnorePatterns": [
"test/output",
"test/specimens"
]
},
"lint-staged": {
"*.js": [
"eslint --fix",
@@ -46,7 +46,7 @@ export default {

### `common`

File name to use in case there are any CSS dependencies that appear in multiple bundles.
File name to use in case there are any CSS dependencies that appear in multiple bundles. Defaults to "common.css".

### `include`/`exclude`

@@ -22,7 +22,7 @@ function extensionless(file) {

module.exports = function(opts) {
const options = Object.assign(Object.create(null), {
common : false,
common : "common.css",

json : false,
map : true,
@@ -36,117 +36,140 @@ module.exports = function(opts) {

const processor = options.processor || new Processor(options);

let runs = 0;

return {
name : "modular-css",
name : "modular-css-rollup",

transform(code, id) {
let removed = [];

if(!filter(id)) {
return null;
}

// If the file is being re-processed we need to remove it to
// avoid cache staleness issues
if(runs) {
removed = processor.remove(id);
if(id in processor.files) {
processor.dependencies(id)
.concat(id)
.forEach((file) => processor.remove(file));
}

return Promise.all(
// Run current file first since it's already in-memory
[ processor.string(id, code) ].concat(
removed.map((file) =>
processor.file(file)
)
)
)
.then((results) => {
const [ result ] = results;
return processor.string(id, code).then((result) => {
const exported = output.join(result.exports);

let out = [
const out = [
`export default ${JSON.stringify(exported, null, 4)};`,
];

// Add dependencies
out = out.concat(
processor.dependencies(id).map((file) =>
`import "${slash(file)}";`
)
);

if(options.namedExports === false) {
return {
code : out.join("\n"),
map,
};
}

Object.keys(exported).forEach((ident) => {
if(keyword.isReservedWordES6(ident) || !keyword.isIdentifierNameES6(ident)) {
this.warn(`Invalid JS identifier "${ident}", unable to export`);
if(options.namedExports) {
Object.keys(exported).forEach((ident) => {
if(keyword.isReservedWordES6(ident) || !keyword.isIdentifierNameES6(ident)) {
this.warn(`Invalid JS identifier "${ident}", unable to export`);

return;
}

return;
}

out.push(`export var ${ident} = ${JSON.stringify(exported[ident])};`);
});
out.push(`export var ${ident} = ${JSON.stringify(exported[ident])};`);
});
}

const dependencies = processor.dependencies(id);

return {
code : out.join("\n"),
map,
dependencies,
};
});
},

buildEnd() {
runs++;
},
async generateBundle(outputOptions, bundles) {
const usage = new Map();
const common = new Map();
const files = [];

let to;

if(!outputOptions.file && !outputOptions.dir) {
to = path.join(process.cwd(), outputOptions.assetFileNames || "");
} else {
to = path.join(
outputOptions.dir ? outputOptions.dir : path.dirname(outputOptions.file),
outputOptions.assetFileNames
);
}

// First pass is used to calculate JS usage of CSS dependencies
Object.keys(bundles).forEach((entry) => {
const file = {
entry,
base : extensionless(entry),

async generateBundle(outputOptions, bundle) {
const bundles = [];
const common = processor.dependencies();
css : [ ],
};

Object.keys(bundle).forEach((entry) => {
const files = Object.keys(bundle[entry].modules).filter(filter);
// Get CSS files being used by each entry point
const css = Object.keys(bundles[entry].modules).filter(filter);

if(!files.length) {
if(!css.length) {
return;
}

// remove the files being exported from the common bundle
files.forEach((file) =>
common.splice(common.indexOf(file), 1)
);
// Get dependency chains for each file
css.forEach((start) => {
const used = processor.dependencies(start).concat(start);

file.css = file.css.concat(used);

bundles.push({
entry,
files,
base : extensionless(entry),
used.forEach((dep) => {
usage.set(dep, usage.has(dep) ? usage.get(dep) + 1 : 1);
});
});

files.push(file);
});

// Common chunk only emitted if configured & if necessary
if(options.common && common.length) {
bundles.push({
// Second pass removes any dependencies appearing in multiple bundles
files.forEach((file) => {
const { css } = file;

file.css = css.filter((dep) => {
if(usage.get(dep) > 1) {
common.set(dep, true);

return false;
}

return true;
});
});

// Add any other files that weren't part of a bundle to the common chunk
Object.keys(processor.files).forEach((file) => {
if(!usage.has(file)) {
common.set(file, true);
}
});

// Common chunk only emitted if necessary
if(common.size) {
files.push({
entry : options.common,
base : extensionless(options.common),
files : common,
css : [ ...common.keys() ],
});
}

await Promise.all(
bundles.map(async ({ base, files }) => {
const css = this.emitAsset(`${base}.css`);

files
.filter(({ css }) => css.length)
.map(async ({ base, css }) => {
const id = this.emitAsset(`${base}.css`);

const result = await processor.output({
to : css,
files,
to,
files : css,
});

this.setAssetSource(css, result.css);
this.setAssetSource(id, result.css);

if(options.json) {
this.emitAsset(`${base}.json`, JSON.stringify(result.compositions, null, 4));
Oops, something went wrong.

0 comments on commit 7347d8f

Please sign in to comment.
You can’t perform that action at this time.