From 684dde0a30e27247c2378d91b92f73abe3757513 Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Sat, 30 Jul 2016 15:04:54 +0300 Subject: [PATCH] Cache resolvedIds in modules to improve incremental build --- src/Bundle.js | 18 ++++++-- src/Module.js | 7 +-- test/function/has-resolved-ids/_config.js | 13 ++++++ test/function/has-resolved-ids/foo.js | 1 + test/function/has-resolved-ids/main.js | 2 + test/test.js | 54 ++++++++++++++++++----- 6 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 test/function/has-resolved-ids/_config.js create mode 100644 test/function/has-resolved-ids/foo.js create mode 100644 test/function/has-resolved-ids/main.js diff --git a/src/Bundle.js b/src/Bundle.js index 96b2486..60ad1fa 100644 --- a/src/Bundle.js +++ b/src/Bundle.js @@ -201,9 +201,18 @@ export default class Bundle { return transform( source, id, this.plugins ); }) .then( source => { - const { code, originalCode, originalSourceMap, ast, sourceMapChain } = source; - - const module = new Module({ id, code, originalCode, originalSourceMap, ast, sourceMapChain, bundle: this }); + const { code, originalCode, originalSourceMap, ast, sourceMapChain, resolvedIds } = source; + + const module = new Module({ + id, + code, + originalCode, + originalSourceMap, + ast, + sourceMapChain, + resolvedIds, + bundle: this + }); this.modules.push( module ); this.moduleById.set( id, module ); @@ -232,7 +241,8 @@ export default class Bundle { fetchAllDependencies ( module ) { return mapSequence( module.sources, source => { - return this.resolveId( source, module.id ) + const resolvedId = module.resolvedIds[ source ]; + return ( resolvedId ? Promise.resolve( resolvedId ) : this.resolveId( source, module.id ) ) .then( resolvedId => { const externalId = resolvedId || ( isRelative( source ) ? resolve( module.id, '..', source ) : source diff --git a/src/Module.js b/src/Module.js index 4d57a19..1cac43a 100644 --- a/src/Module.js +++ b/src/Module.js @@ -17,7 +17,7 @@ import { emptyBlockStatement } from './ast/create.js'; import extractNames from './ast/extractNames.js'; export default class Module { - constructor ({ id, code, originalCode, originalSourceMap, ast, sourceMapChain, bundle }) { + constructor ({ id, code, originalCode, originalSourceMap, ast, sourceMapChain, resolvedIds, bundle }) { this.code = code; this.originalCode = originalCode; this.originalSourceMap = originalSourceMap; @@ -30,7 +30,7 @@ export default class Module { // all dependencies this.sources = []; this.dependencies = []; - this.resolvedIds = blank(); + this.resolvedIds = resolvedIds || blank(); // imports and exports, indexed by local name this.imports = blank(); @@ -657,7 +657,8 @@ export default class Module { code: this.code, originalCode: this.originalCode, ast: this.ast, - sourceMapChain: this.sourceMapChain + sourceMapChain: this.sourceMapChain, + resolvedIds: this.resolvedIds }; } diff --git a/test/function/has-resolved-ids/_config.js b/test/function/has-resolved-ids/_config.js new file mode 100644 index 0000000..b2f3e1a --- /dev/null +++ b/test/function/has-resolved-ids/_config.js @@ -0,0 +1,13 @@ +var path = require( 'path' ); +var assert = require( 'assert' ); + +module.exports = { + description: 'user-facing bundle has resolvedIds map in every modules', + bundle: function ( bundle ) { + assert.ok( bundle.modules[ 0 ].resolvedIds ); + assert.ok( bundle.modules[ 1 ].resolvedIds ); + assert.equal( Object.keys( bundle.modules[ 0 ].resolvedIds ).length, 0 ); + assert.equal( Object.keys( bundle.modules[ 1 ].resolvedIds ).length, 1 ); + assert.equal( bundle.modules[ 1 ].resolvedIds[ './foo' ], path.resolve( __dirname, 'foo.js' ) ); + } +}; diff --git a/test/function/has-resolved-ids/foo.js b/test/function/has-resolved-ids/foo.js new file mode 100644 index 0000000..7a4e8a7 --- /dev/null +++ b/test/function/has-resolved-ids/foo.js @@ -0,0 +1 @@ +export default 42; diff --git a/test/function/has-resolved-ids/main.js b/test/function/has-resolved-ids/main.js new file mode 100644 index 0000000..3206f53 --- /dev/null +++ b/test/function/has-resolved-ids/main.js @@ -0,0 +1,2 @@ +import foo from './foo'; +assert.equal( foo, 42 ); diff --git a/test/test.js b/test/test.js index e68452b..ae8d2d1 100644 --- a/test/test.js +++ b/test/test.js @@ -470,7 +470,7 @@ describe( 'rollup', function () { }); }); - describe('incremental', () => { + describe( 'incremental', () => { function executeBundle ( bundle ) { const cjs = bundle.generate({ format: 'cjs' }); const m = new Function( 'module', 'exports', cjs.code ); @@ -481,44 +481,52 @@ describe( 'rollup', function () { return module.exports; } - let calls; + let resolveIdCalls; + let transformCalls; let modules; const plugin = { - resolveId: id => id, + resolveId: id => { + resolveIdCalls += 1; + return id; + }, load: id => { return modules[ id ]; }, transform: code => { - calls += 1; + transformCalls += 1; return code; } }; beforeEach( () => { - calls = 0; + resolveIdCalls = 0; + transformCalls = 0; modules = { entry: `import foo from 'foo'; export default foo;`, - foo: `export default 42` + foo: `export default 42`, + bar: `export default 21` }; }); - it('does not transforms in the second time', () => { + it('does not resolves id and transforms in the second time', () => { return rollup.rollup({ entry: 'entry', plugins: [ plugin ] }).then( bundle => { - assert.equal( calls, 2 ); + assert.equal( resolveIdCalls, 2 ); + assert.equal( transformCalls, 2 ); return rollup.rollup({ entry: 'entry', plugins: [ plugin ], cache: bundle }); }).then( bundle => { - assert.equal( calls, 2 ); + assert.equal( resolveIdCalls, 3 ); // +1 for entry point which is resolved every time + assert.equal( transformCalls, 2 ); assert.equal( executeBundle( bundle ), 42 ); }); }); @@ -530,7 +538,7 @@ describe( 'rollup', function () { entry: 'entry', plugins: [ plugin ] }).then( bundle => { - assert.equal( calls, 2 ); + assert.equal( transformCalls, 2 ); assert.equal( executeBundle( bundle ), 42 ); modules.foo = `export default 43`; @@ -542,10 +550,34 @@ describe( 'rollup', function () { cache }); }).then( bundle => { - assert.equal( calls, 3 ); + assert.equal( transformCalls, 3 ); assert.equal( executeBundle( bundle ), 43 ); }); }); + + it('resolves id of new imports', () => { + let cache; + + return rollup.rollup({ + entry: 'entry', + plugins: [ plugin ] + }).then( bundle => { + assert.equal( resolveIdCalls, 2 ); + assert.equal( executeBundle( bundle ), 42 ); + + modules.entry = `import bar from 'bar'; export default bar;`; + cache = bundle; + }).then( () => { + return rollup.rollup({ + entry: 'entry', + plugins: [ plugin ], + cache + }); + }).then( bundle => { + assert.equal( resolveIdCalls, 4 ); + assert.equal( executeBundle( bundle ), 21 ); + }); + }); }); describe( 'hooks', () => {