parcel 2.16.3 → 3.0.0-alpha.1
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.
- package/README.md +10 -9
- package/bin/parcel +232 -0
- package/package.json +21 -35
- package/lib/bin.js +0 -4
- package/lib/cli.js +0 -515
- package/src/.eslintrc.json +0 -6
- package/src/bin.js +0 -12
- package/src/cli.js +0 -575
package/README.md
CHANGED
|
@@ -5,33 +5,34 @@
|
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
7
|
[](#backers) [](#sponsors)
|
|
8
|
-
[](https://dev.azure.com/devongovett/devongovett/_build/latest?definitionId=1)
|
|
9
8
|
[](https://www.npmjs.com/package/parcel)
|
|
10
9
|
[](https://www.npmjs.com/package/parcel)
|
|
11
10
|
[](https://discord.gg/XSCzqGRuvr)
|
|
12
11
|
[](https://twitter.com/parceljs)
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
**NOTE: This is Parcel v3 (currently in alpha).**
|
|
14
|
+
|
|
15
|
+
Parcel is a batteries-included build tool for the web. It combines a great out-of-the-box development experience with a scalable architecture that can take your project from just getting started to massive production application.
|
|
15
16
|
|
|
16
17
|
## Features
|
|
17
18
|
|
|
18
|
-
- 😍 **
|
|
19
|
-
- ⚡️ **Lightning fast** – Parcel
|
|
19
|
+
- 😍 **Batteries included** – Parcel supports many languages and file types out of the box, from web technologies like HTML, CSS, and JavaScript, to assets like images, fonts, videos, and more. It has a built-in dev server with hot reloading, beautiful error diagnostics, and much more. No configuration needed!
|
|
20
|
+
- ⚡️ **Lightning fast** – Parcel is written in Rust for native performance, taking advantage of all of the cores on your machine. Extend it with native plugins written in Rust, Go, Swift, or any language that supports the C ABI.
|
|
20
21
|
- 🚀 **Automatic production optimization** – Parcel optimizes your whole app for production automatically. This includes tree-shaking and minifying your JavaScript, CSS, and HTML, resizing and optimizing images, content hashing, automatic code splitting, and much more.
|
|
21
22
|
- 🎯 **Ship for any target** – Parcel automatically transforms your code for your target environments. From modern and legacy browser support, to zero config JSX and TypeScript compilation, Parcel makes it easy to build for any target – or many!
|
|
22
|
-
- 🌍 **Scalable** – Parcel requires zero configuration to get started. But as your application grows and your build requirements become more complex, it's possible to extend Parcel in just about every way. A simple configuration format and powerful
|
|
23
|
+
- 🌍 **Scalable** – Parcel requires zero configuration to get started. But as your application grows and your build requirements become more complex, it's possible to extend Parcel in just about every way. A simple configuration format and powerful native and JavaScript plugin system means Parcel can support projects of any size or complexity.
|
|
23
24
|
|
|
24
25
|
## Getting Started
|
|
25
26
|
|
|
26
27
|
See the following guides in our documentation on how to get started with Parcel.
|
|
27
28
|
|
|
28
|
-
* [Building a webapp with Parcel](https://parceljs.org/getting-started/webapp/)
|
|
29
|
-
* [Building a library with Parcel](https://parceljs.org/getting-started/library/)
|
|
30
|
-
* [Migrating from Parcel
|
|
29
|
+
* [Building a webapp with Parcel](https://v3.parceljs.org/getting-started/webapp/)
|
|
30
|
+
* [Building a library with Parcel](https://v3.parceljs.org/getting-started/library/)
|
|
31
|
+
* [Migrating from Parcel v2](https://v3.parceljs.org/getting-started/migration/)
|
|
31
32
|
|
|
32
33
|
## Documentation
|
|
33
34
|
|
|
34
|
-
Read the docs at https://parceljs.org/docs/.
|
|
35
|
+
Read the docs at https://v3.parceljs.org/docs/.
|
|
35
36
|
|
|
36
37
|
## Community
|
|
37
38
|
|
package/bin/parcel
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shipped as `bin/parcel` in the `parcel` package, and as `bin/parcel3` in
|
|
6
|
+
* `@parcel/parcel3`, which exists so Parcel 3 can be installed beside Parcel 2.
|
|
7
|
+
* Parcel itself is a native executable, published one
|
|
8
|
+
* platform package per target and pulled in through optionalDependencies, so all
|
|
9
|
+
* this file does is hand off to whichever one npm installed for this host.
|
|
10
|
+
*
|
|
11
|
+
* It also tries to take itself out of the loop. Starting Node costs ~30ms on
|
|
12
|
+
* every single invocation, which is a large tax on a tool whose whole
|
|
13
|
+
* point is being fast, so on the first run it rewrites the `node_modules/.bin`
|
|
14
|
+
* entry that launched it into a launcher that execs the binary without Node.
|
|
15
|
+
* See `launcher` for why that launcher looks the way it does.
|
|
16
|
+
*
|
|
17
|
+
* Install scripts would be the natural place for this, but npm and pnpm both
|
|
18
|
+
* block them by default now, so first run is the earliest moment available.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const fs = require('fs');
|
|
22
|
+
const path = require('path');
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The command, which is also the `node_modules/.bin` entry `optimize` rewrites.
|
|
26
|
+
* Taken from this file's own name, so both packages can ship it unchanged.
|
|
27
|
+
*/
|
|
28
|
+
const NAME = path.basename(__filename);
|
|
29
|
+
|
|
30
|
+
/** Prefix of the platform packages, which both packages depend on. */
|
|
31
|
+
const PLATFORM_PACKAGE = '@parcel/parcel3';
|
|
32
|
+
|
|
33
|
+
const EXECUTABLE = process.platform === 'win32' ? 'parcel.exe' : 'parcel';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The platform packages that could serve this host, best first.
|
|
37
|
+
*
|
|
38
|
+
* The names are derived rather than listed, matching what `matrix.mjs` builds
|
|
39
|
+
* from the target table: `process.platform` and `process.arch` are already the
|
|
40
|
+
* values npm's `os` and `cpu` fields use, so a new target needs no change here.
|
|
41
|
+
*
|
|
42
|
+
* On Linux the name also depends on the C library, and rather than detect it and
|
|
43
|
+
* trust the answer we try both: npm, pnpm and Bun all honour the `libc` field,
|
|
44
|
+
* so only the right one is installed and the wrong one simply fails to resolve.
|
|
45
|
+
* The musl check just decides which to try first, for the package managers that
|
|
46
|
+
* ignore `libc` and install both.
|
|
47
|
+
*/
|
|
48
|
+
function candidates() {
|
|
49
|
+
const base = `${PLATFORM_PACKAGE}-${process.platform}-${process.arch}`;
|
|
50
|
+
if (process.platform !== 'linux') return [base];
|
|
51
|
+
return isMusl() ? [`${base}-musl`, base] : [base, `${base}-musl`];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Whether this is a musl system. Biome and friends shell out to `ldd --version`
|
|
56
|
+
* for this; a directory listing costs a fraction of a process.
|
|
57
|
+
*/
|
|
58
|
+
function isMusl() {
|
|
59
|
+
try {
|
|
60
|
+
return fs.readdirSync('/lib').some(entry => entry.startsWith('ld-musl-'));
|
|
61
|
+
} catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function resolveBinary() {
|
|
67
|
+
for (const pkg of candidates()) {
|
|
68
|
+
try {
|
|
69
|
+
return require.resolve(`${pkg}/${EXECUTABLE}`);
|
|
70
|
+
} catch {}
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const binPath = resolveBinary();
|
|
76
|
+
if (binPath == null) {
|
|
77
|
+
// Both cases land here, and the message covers both: the package is missing
|
|
78
|
+
// either because this platform has no prebuilt binary, or because it was
|
|
79
|
+
// skipped at install time.
|
|
80
|
+
process.stderr.write(
|
|
81
|
+
`Parcel could not find the "${
|
|
82
|
+
candidates()[0]
|
|
83
|
+
}" package, which would hold the Parcel ` +
|
|
84
|
+
`binary for ${process.platform} ${process.arch}.\n\n` +
|
|
85
|
+
`Either Parcel publishes no binary for this platform, or the one it does publish was not ` +
|
|
86
|
+
`installed: it comes in through optionalDependencies, so --no-optional and --omit=optional ` +
|
|
87
|
+
`both skip it, as does copying node_modules here from a machine of a different platform. ` +
|
|
88
|
+
`Reinstalling on this machine fixes the second case.\n`,
|
|
89
|
+
);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
optimize();
|
|
94
|
+
run();
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Rewrite the `.bin` entry that launched us so it runs the binary directly.
|
|
98
|
+
*
|
|
99
|
+
* Only an entry that can be proven to refer to this file is ever touched, the
|
|
100
|
+
* write goes through a temp file and an atomic rename, and every failure leaves
|
|
101
|
+
* the entry alone - a slow Parcel is fine, a broken one is not.
|
|
102
|
+
*/
|
|
103
|
+
function optimize() {
|
|
104
|
+
// Windows generates .cmd and .ps1 shims with `node` baked in at install time,
|
|
105
|
+
// so replacing what they point at would only break them.
|
|
106
|
+
if (process.platform === 'win32' || process.env.PARCEL_NO_OPTIMIZE) return;
|
|
107
|
+
|
|
108
|
+
for (const entry of binEntries()) {
|
|
109
|
+
try {
|
|
110
|
+
const stat = fs.lstatSync(entry);
|
|
111
|
+
if (stat.isSymbolicLink()) {
|
|
112
|
+
// npm and Yarn: the .bin entry is a symlink to this file.
|
|
113
|
+
if (fs.realpathSync(entry) !== __filename) continue;
|
|
114
|
+
} else if (stat.isFile()) {
|
|
115
|
+
// pnpm: the .bin entry is a generated sh wrapper that runs `node <this>`.
|
|
116
|
+
if (!wrapsThisFile(fs.readFileSync(entry, 'utf8'))) continue;
|
|
117
|
+
} else {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
replace(entry);
|
|
122
|
+
} catch {}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Whether a generated wrapper points at this file. Package managers write the
|
|
128
|
+
* path relative to their own layout, so the tail below the last `node_modules`
|
|
129
|
+
* is the longest part that is guaranteed to appear verbatim.
|
|
130
|
+
*/
|
|
131
|
+
function wrapsThisFile(contents) {
|
|
132
|
+
const tail = __filename.split(/node_modules[\\/]/).pop();
|
|
133
|
+
return contents.includes(tail) && contents.includes('node');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Every `.bin` entry that could have launched this file. */
|
|
137
|
+
function* binEntries() {
|
|
138
|
+
// What the kernel was handed, before symlinks were resolved: npm and Yarn
|
|
139
|
+
// launch us through the .bin symlink itself.
|
|
140
|
+
const argv1 = process.argv[1];
|
|
141
|
+
if (argv1 && path.basename(path.dirname(argv1)) === '.bin') {
|
|
142
|
+
yield argv1;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Otherwise walk up. `node_modules/.bin` covers a hoisted layout; pnpm keeps
|
|
146
|
+
// the package under `node_modules/.pnpm/...` and the bin beside the store
|
|
147
|
+
// rather than next to the package, so that one is checked separately.
|
|
148
|
+
let dir = path.dirname(__filename);
|
|
149
|
+
for (
|
|
150
|
+
let parent = path.dirname(dir);
|
|
151
|
+
parent !== dir;
|
|
152
|
+
parent = path.dirname(dir)
|
|
153
|
+
) {
|
|
154
|
+
const base = path.basename(dir);
|
|
155
|
+
if (base === 'node_modules') yield path.join(dir, '.bin', NAME);
|
|
156
|
+
if (base === '.pnpm') yield path.join(parent, '.bin', NAME);
|
|
157
|
+
dir = parent;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The launcher gets read two different ways and has to work as both.
|
|
163
|
+
*
|
|
164
|
+
* Normally the kernel reads `#!/bin/sh` and sh execs the binary, which is the
|
|
165
|
+
* whole point: no Node anywhere. But an invocation that started just before the
|
|
166
|
+
* rename has already told Node to load this path as its entry module, and Node
|
|
167
|
+
* opens it ~30ms later - after the swap. Writing anything Node cannot parse, a
|
|
168
|
+
* symlink to the binary included, makes those invocations die trying to read a
|
|
169
|
+
* Mach-O or ELF file as JavaScript.
|
|
170
|
+
*
|
|
171
|
+
* So the rest of the file is also valid JavaScript. `":"` is the sh no-op and a
|
|
172
|
+
* bare string in JS; everything after `//` is an sh argument and a JS comment.
|
|
173
|
+
* A straggler falls through to the last line and runs the binary anyway, paying
|
|
174
|
+
* for Node one final time.
|
|
175
|
+
*/
|
|
176
|
+
function launcher(entry) {
|
|
177
|
+
// Relative to the launcher, so the tree stays movable: renaming the project or
|
|
178
|
+
// copying node_modules into an image keeps it working.
|
|
179
|
+
const rel = path.relative(path.dirname(entry), binPath);
|
|
180
|
+
if (/["$`\\\n]/.test(rel)) return null; // not safely quotable for sh
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
'#!/bin/sh\n' +
|
|
184
|
+
`":" //# ; exec "\${0%/*}/${rel}" "$@"\n` +
|
|
185
|
+
`require("child_process").spawnSync(require("path").join(__dirname, ${JSON.stringify(
|
|
186
|
+
rel,
|
|
187
|
+
)}), ` +
|
|
188
|
+
`process.argv.slice(2), {stdio: "inherit"});\n`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Write beside the entry, then rename over it. A concurrent invocation sees
|
|
194
|
+
* either the old entry or the new one, never a half-written file.
|
|
195
|
+
*/
|
|
196
|
+
function replace(entry) {
|
|
197
|
+
const contents = launcher(entry);
|
|
198
|
+
if (contents == null) return;
|
|
199
|
+
|
|
200
|
+
const tmp = `${entry}.${process.pid}.tmp`;
|
|
201
|
+
try {
|
|
202
|
+
fs.writeFileSync(tmp, contents, {mode: 0o755});
|
|
203
|
+
fs.renameSync(tmp, entry);
|
|
204
|
+
} catch (err) {
|
|
205
|
+
try {
|
|
206
|
+
fs.unlinkSync(tmp);
|
|
207
|
+
} catch {}
|
|
208
|
+
throw err;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function run() {
|
|
213
|
+
const args = process.argv.slice(2);
|
|
214
|
+
|
|
215
|
+
// Replacing this process rather than forking one keeps signals, the exit code
|
|
216
|
+
// and terminal handling native. Node gained execve in 23.11 and never has it
|
|
217
|
+
// on Windows, hence the fallback.
|
|
218
|
+
if (typeof process.execve === 'function') {
|
|
219
|
+
process.execve(binPath, [binPath, ...args], process.env);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const result = require('child_process').spawnSync(binPath, args, {
|
|
223
|
+
stdio: 'inherit',
|
|
224
|
+
});
|
|
225
|
+
if (result.error) throw result.error;
|
|
226
|
+
// Signal death has no exit code of its own; 128 + signal is what a shell reports.
|
|
227
|
+
process.exit(
|
|
228
|
+
result.signal
|
|
229
|
+
? 128 + require('os').constants.signals[result.signal]
|
|
230
|
+
: result.status,
|
|
231
|
+
);
|
|
232
|
+
}
|
package/package.json
CHANGED
|
@@ -1,45 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "parcel",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.1",
|
|
4
4
|
"description": "Blazing fast, zero configuration web application bundler",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"publishConfig": {
|
|
7
|
-
"access": "public"
|
|
8
|
-
},
|
|
9
|
-
"funding": {
|
|
10
|
-
"type": "opencollective",
|
|
11
|
-
"url": "https://opencollective.com/parcel"
|
|
12
|
-
},
|
|
13
6
|
"repository": {
|
|
14
7
|
"type": "git",
|
|
15
8
|
"url": "https://github.com/parcel-bundler/parcel.git"
|
|
16
9
|
},
|
|
17
|
-
"bin":
|
|
18
|
-
|
|
19
|
-
"source": "src/bin.js",
|
|
20
|
-
"engines": {
|
|
21
|
-
"node": ">= 16.0.0"
|
|
10
|
+
"bin": {
|
|
11
|
+
"parcel": "bin/parcel"
|
|
22
12
|
},
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
"@parcel/logger": "2.16.3",
|
|
31
|
-
"@parcel/package-manager": "2.16.3",
|
|
32
|
-
"@parcel/reporter-cli": "2.16.3",
|
|
33
|
-
"@parcel/reporter-dev-server": "2.16.3",
|
|
34
|
-
"@parcel/reporter-tracer": "2.16.3",
|
|
35
|
-
"@parcel/utils": "2.16.3",
|
|
36
|
-
"chalk": "^4.1.2",
|
|
37
|
-
"commander": "^12.1.0",
|
|
38
|
-
"get-port": "^4.2.0"
|
|
39
|
-
},
|
|
40
|
-
"devDependencies": {
|
|
41
|
-
"@babel/core": "^7.22.11",
|
|
42
|
-
"@parcel/babel-register": "2.16.3"
|
|
13
|
+
"files": [
|
|
14
|
+
"bin",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">= 18"
|
|
43
20
|
},
|
|
44
|
-
"
|
|
45
|
-
|
|
21
|
+
"optionalDependencies": {
|
|
22
|
+
"@parcel/parcel3-darwin-arm64": "3.0.0-alpha.1",
|
|
23
|
+
"@parcel/parcel3-win32-arm64": "3.0.0-alpha.1",
|
|
24
|
+
"@parcel/parcel3-linux-arm64": "3.0.0-alpha.1",
|
|
25
|
+
"@parcel/parcel3-linux-arm64-musl": "3.0.0-alpha.1",
|
|
26
|
+
"@parcel/parcel3-darwin-x64": "3.0.0-alpha.1",
|
|
27
|
+
"@parcel/parcel3-win32-x64": "3.0.0-alpha.1",
|
|
28
|
+
"@parcel/parcel3-linux-x64": "3.0.0-alpha.1",
|
|
29
|
+
"@parcel/parcel3-linux-x64-musl": "3.0.0-alpha.1"
|
|
30
|
+
}
|
|
31
|
+
}
|
package/lib/bin.js
DELETED