@rollup-extras/plugin-script-loader 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +4 -0
  2. package/index.js +35 -29
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ ![Coverage](https://raw.githubusercontent.com/kshutkin/rollup-extras/refs/heads/coverage/plugin-script-loader/badge.svg)
2
+
1
3
  # Plugin Script Loader
2
4
 
3
5
  Rollup plugin to mimic Webpack's `script-loader` inline behavior. Inlines raw scripts into the bundle in import order, or emits them as a separate asset file for non-module, non-strict mode execution.
@@ -40,6 +42,8 @@ The plugin intercepts imports that start with a configurable prefix (`script!` b
40
42
  - **`emit: 'inline'`** (default) — Inlines the raw source code directly into the bundle at the import site
41
43
  - **`emit: 'asset'`** — Collects all scripts and emits them as a separate concatenated asset file
42
44
 
45
+ In asset mode, script order follows static dependency evaluation across modules: a script imported through a helper runs before a later direct import. Shared dependencies and cycles do not duplicate scripts. Scripts force-loaded by other plugins without a reachable import edge are appended in load order.
46
+
43
47
  Because the code is handled as real JavaScript (not wrapped in `eval()` or `new Function()`), it:
44
48
 
45
49
  - Preserves **import order** — scripts appear exactly as imported
package/index.js CHANGED
@@ -43,8 +43,6 @@ export default function (options = {}) {
43
43
 
44
44
  const scripts = new Map();
45
45
 
46
- const importOrder = [];
47
-
48
46
  async function tryReadSourcemap(filePath, code) {
49
47
 
50
48
  const inlineMatch = code.match(
@@ -77,6 +75,39 @@ export default function (options = {}) {
77
75
  return code.replace(/\n?\/\/[#@]\s*sourceMappingURL=.+?\s*$/, '');
78
76
  }
79
77
 
78
+ function getOrderedScripts(bundle) {
79
+ const visited = new Set();
80
+
81
+ const ordered = [];
82
+
83
+ const dynamicImports = [];
84
+
85
+ const visit = id => {
86
+ if (visited.has(id)) return;
87
+ visited.add(id);
88
+ const info = this.getModuleInfo(id);
89
+ if (!info || info.isExternal) return;
90
+ for (const dependency of info.importedIds) visit(dependency);
91
+ const script = scripts.get(id);
92
+ if (script) ordered.push(script);
93
+ dynamicImports.push(...info.dynamicallyImportedIds);
94
+ };
95
+
96
+ for (const item of Object.values(bundle)) {
97
+ if (item.type === 'chunk' && item.isEntry && item.facadeModuleId) visit(item.facadeModuleId);
98
+ }
99
+ for (const id of this.getModuleIds()) {
100
+ if (this.getModuleInfo(id)?.isEntry) visit(id);
101
+ }
102
+
103
+ for (const id of dynamicImports) visit(id);
104
+
105
+ for (const [id, script] of scripts) {
106
+ if (!visited.has(id)) ordered.push(script);
107
+ }
108
+ return ordered;
109
+ }
110
+
80
111
  return ({
81
112
  name: pluginName,
82
113
 
@@ -111,18 +142,6 @@ export default function (options = {}) {
111
142
  };
112
143
  },
113
144
 
114
- moduleParsed(moduleInfo) {
115
- if (emit !== 'asset') {
116
- return;
117
- }
118
-
119
- for (const importedId of moduleInfo.importedIds) {
120
- if (importedId.startsWith(scriptPrefix) && !importOrder.includes(importedId)) {
121
- importOrder.push(importedId);
122
- }
123
- }
124
- },
125
-
126
145
  async load(id) {
127
146
  if (!id.startsWith(scriptPrefix)) {
128
147
  return null;
@@ -174,23 +193,11 @@ export default function (options = {}) {
174
193
  return;
175
194
  }
176
195
 
177
- const sortedEntries = Array.from(scripts.entries())
178
- .sort(([idA], [idB]) => {
179
- const orderA = importOrder.indexOf(idA);
180
- const orderB = importOrder.indexOf(idB);
181
-
182
- if (orderA !== -1 && orderB !== -1) {
183
- return orderA - orderB;
184
- }
185
- if (orderA !== -1) return -1;
186
- if (orderB !== -1) return 1;
187
- return 0;
188
- })
189
- .map(([, entry]) => entry);
196
+ const sortedEntries = getOrderedScripts.call(this, bundle);
190
197
 
191
198
  const outputDir = _outputOptions.dir ?? (_outputOptions.file ? dirname(_outputOptions.file) : process.cwd());
192
199
 
193
- const magicBundle = new Bundle({ separator: '\n' });
200
+ const magicBundle = new Bundle({ separator: '\n;\n' });
194
201
 
195
202
  for (const entry of sortedEntries) {
196
203
  const ms = new MagicString(entry.code, {
@@ -313,7 +320,6 @@ export default function (options = {}) {
313
320
 
314
321
  closeBundle() {
315
322
  scripts.clear();
316
- importOrder.length = 0;
317
323
  },
318
324
  });
319
325
  }
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.1",
2
+ "version": "0.1.3",
3
3
  "license": "MIT",
4
4
  "name": "@rollup-extras/plugin-script-loader",
5
5
  "author": "Konstantin Shutkin",
@@ -37,7 +37,7 @@
37
37
  "@ampproject/remapping": "^2.3.0",
38
38
  "@niceties/logger": "^2.1.0",
39
39
  "magic-string": "^0.30.21",
40
- "@rollup-extras/utils": "^2.0.0"
40
+ "@rollup-extras/utils": "^2.0.2"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "rollup": "^4.0.0"