Skip to content

Commit a69b8f0

Browse files
committed
feat(origin-loader): build resources now set their Origin using aurelia-metadata
fixes aurelia/loader-webpack#12 and aurelia/templating#418
1 parent 32a637a commit a69b8f0

File tree

3 files changed

+118
-30
lines changed

3 files changed

+118
-30
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"cheerio": "^0.20.0",
3636
"debug": "^2.2.0",
3737
"execa": "^0.4.0",
38+
"loader-utils": "^0.2.15",
3839
"object.assign": "^4.0.3",
3940
"recursive-readdir": "^2.0.0",
4041
"upath": "^0.1.7"

src/index.js

+98-30
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,49 @@ class AureliaWebpackPlugin {
5959
}
6060

6161
apply(compiler) {
62-
compiler.plugin('context-module-factory', cmf => {
62+
const options = this.options;
63+
const self = this;
64+
65+
compiler.plugin('run', function(compiler, callback) {
66+
debug('run');
67+
resolveTemplates.processAll(options).then(contextElements => {
68+
compiler.__aureliaContextElements = contextElements;
69+
debug('finished run: got contextElements');
70+
callback();
71+
}, (e) => {
72+
handleError(e);
73+
return callback(error);
74+
});
75+
});
76+
77+
compiler.plugin('watch-run', function(watching, callback) {
78+
resolveTemplates.processAll(options).then(contextElements => {
79+
watching.compiler.__aureliaContextElements = contextElements;
80+
debug('finished watch-run: got contextElements');
81+
callback();
82+
}, (e) => {
83+
handleError(e);
84+
return callback(error);
85+
});
86+
});
87+
88+
compiler.plugin('context-module-factory', function (cmf) {
89+
var contextElements = compiler.__aureliaContextElements;
90+
debug('context-module-factory');
91+
6392
cmf.plugin('before-resolve', (result, callback) => {
6493
if (!result) return callback();
65-
if (this.options.resourceRegExp.test(result.request)) {
66-
result.request = this.options.src;
94+
if (self.options.resourceRegExp.test(result.request)) {
95+
result.request = self.options.src;
6796
}
6897
return callback(null, result);
6998
});
99+
70100
cmf.plugin('after-resolve', (result, callback) => {
71101
if (!result) return callback();
102+
72103
const resourcePath = path.normalizeSafe(result.resource);
73-
if (this.options.src.indexOf(resourcePath, this.options.src.length - resourcePath.length) !== -1) {
104+
if (self.options.src.indexOf(resourcePath, self.options.src.length - resourcePath.length) !== -1) {
74105
const resolveDependencies = result.resolveDependencies;
75106

76107
// substitute resolveDependencies method with an enhanced version:
@@ -88,39 +119,76 @@ class AureliaWebpackPlugin {
88119
dependencies.push(dependency);
89120
}
90121

91-
resolveTemplates.processAll(this.options).then(contextElements => {
92-
for (let requireRequestPath of Object.keys(contextElements).reverse()) {
93-
try {
94-
const resource = contextElements[requireRequestPath];
95-
// ensure we have './' at the beginning of the request path
96-
requireRequestPath = path.joinSafe('./', requireRequestPath);
97-
let newDependency = new ContextElementDependency(getPath(resource), requireRequestPath);
98-
if (resource.hasOwnProperty('optional'))
99-
newDependency.optional = !!resource.optional;
100-
else
101-
newDependency.optional = true;
102-
let previouslyAdded = dependencies.findIndex(dependency => dependency.userRequest === requireRequestPath);
103-
if (previouslyAdded > -1) {
104-
dependencies[previouslyAdded] = newDependency;
105-
} else {
106-
dependencies.push(newDependency);
107-
}
108-
} catch (e) {
109-
handleError(e);
122+
for (let requireRequestPath of Object.keys(contextElements).reverse()) {
123+
try {
124+
const resource = contextElements[requireRequestPath];
125+
// ensure we have './' at the beginning of the request path
126+
requireRequestPath = path.joinSafe('./', requireRequestPath);
127+
let newDependency = new ContextElementDependency(self.getPath(resource), requireRequestPath);
128+
if (resource.hasOwnProperty('optional'))
129+
newDependency.optional = !!resource.optional;
130+
else
131+
newDependency.optional = true;
132+
let previouslyAdded = dependencies.findIndex(dependency => dependency.userRequest === requireRequestPath);
133+
if (previouslyAdded > -1) {
134+
dependencies[previouslyAdded] = newDependency;
135+
} else {
136+
dependencies.push(newDependency);
110137
}
111-
// TODO: optional filtering of context (things we don't want to require)
138+
} catch (e) {
139+
handleError(e);
112140
}
113-
114-
return callback(null, dependencies);
115-
}, (e) => {
116-
handleError(e);
117-
return callback(error);
118-
});
141+
// TODO: optional filtering of context (things we don't want to require)
142+
}
143+
144+
return callback(null, dependencies);
119145
});
120146
}
121147
return callback(null, result);
122148
});
123149
});
150+
151+
/**
152+
* used to inject Aurelia's Origin to all build resources
153+
*/
154+
compiler.plugin('compilation', function(compilation) {
155+
debug('compilation');
156+
const contextElements = compiler.__aureliaContextElements;
157+
let paths = [];
158+
try {
159+
paths = Object.getOwnPropertyNames(contextElements);
160+
} catch (e) {
161+
console.error('No context elements');
162+
}
163+
164+
compilation.plugin('normal-module-loader', function(loaderContext, module) {
165+
// this is where all the modules are loaded
166+
// one by one, no dependencies are created yet
167+
if (typeof module.resource == 'string' && /\.(js|ts)x?$/i.test(module.resource)) {
168+
let moduleId;
169+
if (module.resource.startsWith(options.src)) {
170+
moduleId = path.relative(options.src, module.resource);
171+
}
172+
if (!moduleId && typeof module.userRequest == 'string') {
173+
moduleId = paths.find(originPath => contextElements[originPath].source === module.userRequest);
174+
if (moduleId) {
175+
moduleId = path.normalize(moduleId);
176+
}
177+
}
178+
if (!moduleId && typeof module.rawRequest == 'string' && !module.rawRequest.startsWith('.')) {
179+
// requested module:
180+
let index = paths.indexOf(module.rawRequest);
181+
if (index >= 0) {
182+
moduleId = module.rawRequest;
183+
}
184+
}
185+
if (moduleId) {
186+
const originLoader = path.join(__dirname, 'origin-loader.js') + '?' + JSON.stringify({ moduleId });
187+
module.loaders.unshift(originLoader);
188+
}
189+
}
190+
});
191+
});
124192
}
125193
}
126194

src/origin-loader.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const loaderUtils = require('loader-utils');
2+
3+
module.exports = function(source, map) {
4+
const options = loaderUtils.parseQuery(this.query);
5+
const moduleId = options.moduleId;
6+
this.cacheable();
7+
8+
const newSource = source + `
9+
import {Origin} from 'aurelia-metadata';
10+
for (var exportName in module.exports) {
11+
Origin.set(module.exports[exportName], new Origin(${JSON.stringify(moduleId)}, exportName));
12+
}`;
13+
14+
this.callback(null, newSource, map);
15+
16+
if (options.debug) {
17+
console.log('changed source query', options);
18+
}
19+
}

0 commit comments

Comments
 (0)