Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: store low level resolutions from built module #392

Merged
merged 1 commit into from
Jul 2, 2018
Merged
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
18 changes: 9 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,15 +378,6 @@ class HardSourceWebpackPlugin {
});
}

function runVerify(_compiler) {
if (!active) {
return Promise.resolve();
}

const stats = {};
return pluginCompat.promise(compiler, '_hardSourceVerifyCache', []);
}

compilerHooks.watchRun.tapPromise(
'HardSource - index - readOrReset',
runReadOrReset,
Expand Down Expand Up @@ -515,6 +506,15 @@ class HardSourceWebpackPlugin {

new ChalkLoggerPlugin(this.options.info).apply(compiler);

function runVerify(_compiler) {
if (!active) {
return Promise.resolve();
}

const stats = {};
return pluginCompat.promise(compiler, '_hardSourceVerifyCache', []);
}

compilerHooks.watchRun.tapPromise('HardSource - index - verify', runVerify);
compilerHooks.run.tapPromise('HardSource - index - verify', runVerify);

Expand Down
35 changes: 35 additions & 0 deletions lib/TransformNormalModuleFactoryPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,41 @@ class NormalModuleFactoryPlugin {
// compilation.__hardSourceFileMd5s = fileMd5s;
// compilation.__hardSourceCachedMd5s = cachedMd5s;

const compilationHooks = pluginCompat.hooks(compilation);
compilationHooks.buildModule.tap(
'HardSource - TransformNormalModuleFactoryPlugin',
module => {
if (module.constructor.name === 'NormalModule') {
const _createLoaderContext = module.createLoaderContext;
module.__hardSource_resolved = {};
module.createLoaderContext = (...args) => {
const loaderContext = _createLoaderContext.call(
module,
...args,
);
const _resolve = loaderContext.resolve;
loaderContext.resolve = (context, request, callback) => {
_resolve.call(
loaderContext,
context,
request,
(err, result) => {
module.__hardSource_resolved[
JSON.stringify({ context, request })
] = {
resource: result,
resolveOptions: module.resolveOptions,
};
callback(err, result);
},
);
};
return loaderContext;
};
}
},
);

const normalModuleFactoryHooks = pluginCompat.hooks(
normalModuleFactory,
);
Expand Down
108 changes: 106 additions & 2 deletions lib/TransformNormalModulePlugin.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const NormalModule = require('webpack/lib/NormalModule');
const Module = require('webpack/lib/Module');

const nodeObjectHash = require('node-object-hash');

const logMessages = require('./util/log-messages');
const {
relateNormalPath,
Expand All @@ -11,6 +13,44 @@ const {
const pluginCompat = require('./util/plugin-compat');
const serial = require('./util/serial');

const serialResolveRequest = serial.created({
context: serial.path,
request: serial.request,
});

const serialResolved = serial.created({
// context: serial.path,
// request: serial.request,
// userRequest: serial.request,
// rawRequest: serial.request,
resource: serial.request,
resolveOptions: serial.identity,
// loaders: serial.loaders,
});

const serialResolvedMap = {
freeze(arg, module, extra) {
const resolved = [];
for (const key in arg) {
const thawedKey = JSON.parse(key);
resolved.push([
serialResolveRequest.freeze(thawedKey, thawedKey, extra),
serialResolved.freeze(arg[key], arg[key], extra),
]);
}
return resolved;
},
thaw(arg, frozen, extra) {
const resolved = {};
for (const item of arg) {
const key = serialResolveRequest.thaw(item[0], item[0], extra);
const value = serialResolved.thaw(item[1], item[1], extra);
resolved[JSON.stringify(key)] = value;
}
return resolved;
},
};

const serialNormalModule4 = serial.serial('NormalModule', {
constructor: serial.constructed(NormalModule, {
data: serial.pipe(
Expand Down Expand Up @@ -124,6 +164,8 @@ const serialNormalModule4 = serial.serial('NormalModule', {
_buildHash: serial.identity,
hash: serial.identity,
_lastSuccessfulBuildMeta: serial.identity,

__hardSource_resolved: serialResolvedMap,
}),

dependencyBlock: serial.dependencyBlock,
Expand Down Expand Up @@ -159,6 +201,9 @@ const needRebuild4 = function() {
}
const fileHashes = this.__hardSourceFileMd5s;
const cachedHashes = this.__hardSourceCachedMd5s;
const resolvedLast = this.__hardSource_resolved;
const missingCache = this.__hardSource_missingCache;

for (const file of this.buildInfo.fileDependencies) {
if (!cachedHashes[file] || fileHashes[file] !== cachedHashes[file]) {
this.cacheItem.invalid = true;
Expand All @@ -173,7 +218,33 @@ const needRebuild4 = function() {
return true;
}
}
return false;

let resolvedNeedRebuild = false;
for (const _resolveKey in resolvedLast) {
const resolveKey = JSON.parse(_resolveKey);
const resolved = resolvedLast[_resolveKey];
let normalId = 'normal';
if (resolved.resolveOptions) {
normalId = `normal-${new nodeObjectHash({ sort: false }).hash(
resolved.resolveOptions,
)}`;
}
const resolvedMissing =
missingCache[normalId] &&
missingCache[normalId][
JSON.stringify([resolveKey.context, resolved.resource.split('?')[0]])
];
if (!resolvedMissing || resolvedMissing.invalid) {
resolved.invalid = true;
resolved.invalidReason = `resolved normal invalid${
resolvedMissing
? ` ${resolvedMissing.invalidReason}`
: ': resolve entry not in cache'
}`;
resolvedNeedRebuild = true;
}
}
return resolvedNeedRebuild;
};

const serialNormalModule3 = serial.serial('NormalModule', {
Expand Down Expand Up @@ -275,6 +346,8 @@ const serialNormalModule3 = serial.serial('NormalModule', {
warnings: serial.moduleWarning,
errors: serial.moduleError,
_source: serial.source,

__hardSource_resolved: serialResolvedMap,
}),

hash: {
Expand Down Expand Up @@ -320,6 +393,9 @@ const needRebuild3 = function() {
}
const fileHashes = this.__hardSourceFileMd5s;
const cachedHashes = this.__hardSourceCachedMd5s;
const resolvedLast = this.__hardSource_resolved;
const missingCache = this.__hardSource_missingCache;

for (const file of this.fileDependencies) {
if (!cachedHashes[file] || fileHashes[file] !== cachedHashes[file]) {
this.cacheItem.invalid = true;
Expand All @@ -334,7 +410,34 @@ const needRebuild3 = function() {
return true;
}
}
return false;

let resolvedNeedRebuild = false;
for (const _resolveKey in resolvedLast) {
const resolveKey = JSON.parse(_resolveKey);
const resolved = resolvedLast[_resolveKey];
let normalId = 'normal';
if (resolved.resolveOptions) {
normalId = `normal-${new nodeObjectHash({ sort: false }).hash(
resolved.resolveOptions,
)}`;
}
const resolvedMissing =
missingCache[normalId] &&
missingCache[normalId][
JSON.stringify([resolveKey.context, resolved.resource.split('?')[0]])
];
if (!resolvedMissing || resolvedMissing.invalid) {
resolved.invalid = true;
resolved.invalidReason = `resolved normal invalid${
resolvedMissing
? ` ${resolvedMissing.invalidReason}`
: ': resolve entry not in cache'
}`;
resolvedNeedRebuild = true;
}
}

return resolvedNeedRebuild;
};

const cacheable = module =>
Expand Down Expand Up @@ -498,6 +601,7 @@ class TransformNormalModulePlugin {
m.cacheItem = frozen;
m.__hardSourceFileMd5s = compilation.__hardSourceFileMd5s;
m.__hardSourceCachedMd5s = compilation.__hardSourceCachedMd5s;
m.__hardSource_missingCache = compiler.__hardSource_missingCache;
m.needRebuild = needRebuild;

// Unbuild if there is no cache. The module will be rebuilt. Not
Expand Down
1 change: 1 addition & 0 deletions lib/util/plugin-compat.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const knownPluginRegistrations = {
Compilation: {
needAdditionalPass: ['sync', []],
succeedModule: ['sync', ['module']],
buildModule: ['sync', ['module']],
},
Compiler: {
afterCompile: ['asyncSerial', ['compilation']],
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/loader-custom-resolve-request/fab/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = function(n) {
return n * (n > 1 ? n - 1 : 1);
};
3 changes: 3 additions & 0 deletions tests/fixtures/loader-custom-resolve-request/fib.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = function(n) {
return n + (n > 0 ? n - 2 : 0);
};
3 changes: 3 additions & 0 deletions tests/fixtures/loader-custom-resolve-request/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var fib = require('./loader!./fib');

console.log(fib(3));
7 changes: 7 additions & 0 deletions tests/fixtures/loader-custom-resolve-request/loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = function(source) {
this.cacheable && this.cacheable();
return new Promise(
(f, e) => this.resolve(this.context, './fab', (er, v) => er ? e(er) : f(v))
)
.then(v => JSON.stringify(v));
};
18 changes: 18 additions & 0 deletions tests/fixtures/loader-custom-resolve-request/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var HardSourceWebpackPlugin = require('../../..');

module.exports = {
context: __dirname,
entry: './index.js',
output: {
path: __dirname + '/tmp',
filename: 'main.js',
},
plugins: [
new HardSourceWebpackPlugin({
cacheDirectory: 'cache',
environmentHash: {
root: __dirname + '/../../..',
},
}),
],
};
2 changes: 1 addition & 1 deletion tests/fixtures/plugin-mini-css-extract-change/index.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
.hello {
color: blue;
color: red;
}
23 changes: 23 additions & 0 deletions tests/loaders-webpack-3.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,26 @@ describeWP(3)('loader webpack 3 use', function() {
itCompilesTwice('loader-worker-1dep', {exportStats: true});

});

describeWP(3)('loader webpack 3 use - builds changes', function() {

itCompilesChange('loader-custom-resolve-request', {
'fab.js': null,
}, {
'fab.js': 'bar',
}, function(output) {
expect(output.run1['main.js'].toString()).to.match(/fab(\/|\\\\|\\\\\\\\)index\.js/);
expect(output.run2['main.js'].toString()).to.match(/fab\.js/);
});

itCompilesChange('loader-custom-resolve-request', {
'fab.js': 'bar',
}, {
'fab.js': null,
}, function(output) {
expect(output.run1['main.js'].toString()).to.match(/fab\.js/);
expect(output.run2['main.js'].toString()).to.match(/fab(\/|\\\\|\\\\\\\\)index\.js/);
});

});