UNPKG

3.38 kBJavaScriptView Raw
1// Temporarily retain all modules todo in bundler
2const {parse, resolveModuleId} = require('dumber-module-loader/dist/id-utils');
3
4const USER = '0';
5const PACKAGE = '1';
6const USER_OR_PACKAGE = '2';
7
8const SERIAL_GROUP = '3';
9
10module.exports = class ModulesTodo {
11 constructor() {
12 this._reset();
13 }
14
15 _reset() {
16 // {'0:id': ['required_by_ids']}
17 this.todos = Object.create(null);
18 }
19
20 hasTodo() {
21 return Object.keys(this.todos).length > 0;
22 }
23
24 // add deps from tracedUnit
25 process(unit) {
26 const {moduleId, packageName, deps} = unit;
27
28 deps.forEach(d => {
29 const parsedId = parse(resolveModuleId(moduleId, d));
30
31 if (!parsedId.prefix && (
32 parsedId.ext === '.css' ||
33 parsedId.ext === '.less' ||
34 parsedId.ext === '.scss' ||
35 parsedId.ext === '.sass' ||
36 parsedId.ext === '.styl'
37 )) {
38 this.needCssInjection = true;
39 }
40
41 let space;
42 if (packageName) {
43 space = PACKAGE;
44 } else if (isRelative(d)) {
45 // local relative
46 space = USER;
47 } else {
48 space = USER_OR_PACKAGE;
49 }
50
51 if (parsedId.prefix &&
52 parsedId.prefix !== 'text!' &&
53 parsedId.prefix !== 'json!' &&
54 parsedId.prefix !== 'raw!') {
55 // Trace any unknown plugin module.
56 // For simplicity, push it to next resolve cycle.
57 const pluginName = parsedId.prefix.slice(0, -1);
58
59 let pluginSpace = space;
60 if (space !== PACKAGE) pluginSpace = USER_OR_PACKAGE;
61 const key = pluginSpace + ':' + pluginName;
62 if (!this.todos[key]) this.todos[key] = [];
63 this.todos[key].push(moduleId);
64 }
65
66 const key = space + ':' + parsedId.cleanId;
67 if (!this.todos[key]) this.todos[key] = [];
68 this.todos[key].push(moduleId);
69 });
70 }
71
72 // call the cb to acquire missing deps
73 acquire(cb) {
74 if (Object.keys(this.todos).length === 0) {
75 return Promise.resolve();
76 }
77
78 const {todos} = this;
79 this._reset();
80
81 // put module ids from same package in group
82 // { '1:some-package': ['1:some-package', '1:some-package/foo/bar']}
83 const keys = Object.keys(todos).sort();
84 const groups = {};
85 groups[SERIAL_GROUP] = [];
86
87 keys.forEach(key => {
88 const [space, id] = spaceAndId(key);
89
90 // Don't need the parallel optimization when running
91 // in nodejs.
92 if (!process.browser || space === USER) {
93 groups[SERIAL_GROUP].push(key);
94 } else {
95 const packageName = parse(id).parts[0];
96 const group = space + ':' + packageName;
97 if (!groups[group]) groups[group] = [];
98 groups[group].push(key);
99 }
100 });
101
102 // parallel groups
103 return Promise.all(Object.values(groups).map(keys => {
104 // serialise module ids within one group (same npm package)
105 // because packageReader should be created only once.
106 let p = Promise.resolve();
107
108 keys.forEach(key => {
109 const [space, id] = spaceAndId(key);
110 const requiredBy = todos[key];
111
112 p = p.then(() => cb(id, {
113 user: space !== PACKAGE,
114 package: space !== USER,
115 requiredBy
116 }));
117 });
118
119 return p;
120 }));
121 }
122};
123
124function spaceAndId(key) {
125 return [key.slice(0, 1), key.slice(2)];
126}
127
128function isRelative(id) {
129 return parse(id).bareId.startsWith('.');
130}