I managed to get Babel/JSX working on Snowpack, with a number of bug workarounds.
Here are the Snowpack bugs:
"build:" step or it refuses to build anything. (Fix merged but not yet released)"@snowpack/plugin-babel" and not just "babel" (Documentation fix merged but not yet deployed).jsx; Snowpack fails with a parse error if you put it in a .js file. (Documentation fix merged but not yet deployed)With that done, I was able to convince Snowpack to work only when I imported a full path to the ESM js file, e.g. import {renderer} from '@bikeshaving/crank/esm/dom.js';
I couldn't get it to work with import {renderer} from '@bikeshaving/crank/dom', even in my PR branch for #88. Snowpack assumes that subpackages have their own package.json file. It gave up when it couldn't find @bikeshaving/crank/dom/package.json.
The conclusion I draw from this is that Crank would need to provide a dom/package.json and perhaps html/package.json to satisfy Snowpack. I guess you could argue that this is a bug in Snowpack, but I bet they won't fix it, because other frameworks with subpackages _do_ provide package.json files for their subpackages, e.g. preact/hooks provides preact/hooks/package.json.
Repro script:
#!/bin/sh
rm -rf snowpack-bikeshaving-example
npm init snowpack-app snowpack-bikeshaving-example --template @snowpack/app-template-blank
cd snowpack-bikeshaving-example
git init
git add -A
git commit -m "initial commit, right after init"
cat <<EOF > snowpack.config.json
{
"scripts": {
"build:dummy": "cat",
"plugin:js,jsx": "@snowpack/plugin-babel"
}
}
EOF
cat <<EOF > babel.config.json
{
"presets": ["@babel/preset-react"]
}
EOF
rm src/index.js
cat <<EOF > src/index.jsx
/** @jsx createElement */
import {createElement} from '@bikeshaving/crank/esm/index.js';
import {renderer} from '@bikeshaving/crank/esm/dom.js';
renderer.render(<h1>Hello world</h1>, document.body);
EOF
npm i -D @snowpack/plugin-babel @babel/preset-react
npm i @bikeshaving/crank
npm run build
I filed https://www.pika.dev/npm/snowpack/discuss/151 on this; it's arguably Snowpack's fault.
Does this bug have a github issue or do I have to use pikapkg discussions 😅
You have to use pikapkg. Also, I was poking at this recently and this bug is wayyyy out of date. Snowpack 2 has churned a lot in the last week and a half; my repro no longer works; my _workaround_ no longer works.
https://www.pika.dev/npm/snowpack/discuss/185
"snowpack add" fails on scoped packages, e.g. "@angular/core"
(so of course it fails with @bikeshaving/crank)
Here's an updated repro script. It doesn't work, and I can't figure out how to make it work.
#!/bin/sh -ex
rm -rf snowpack-example
npm init snowpack-app snowpack-example --template @snowpack/app-template-blank
cd snowpack-example
cat <<EOF > package.json
{
"scripts": {
"prepare": "snowpack",
"start": "snowpack dev",
"build": "snowpack build",
"test": "echo \"This template does not include a test runner by default.\" && exit 1",
"format": "prettier --write 'src/**/*.js'",
"lint": "prettier --check 'src/**/*.js'"
},
"webDependencies": {
"@bikeshaving/crank": "0.1.2"
},
"devDependencies": {
"prettier": "^2.0.0",
"snowpack": "^2.0.0-0"
}
}
EOF
cat <<EOF > src/index.js
import {createElement} from '@bikeshaving/crank';
import {renderer} from '@bikeshaving/crank/dom';
renderer.render(createElement('h1', null, "Hello world"));
EOF
npm run prepare
npm start
Here's the error I get:
✖ Package "@bikeshaving/crank/dom" not found. Have you installed it?
Changing the import to '@bikeshaving/crank/dom.js' or '@bikeshaving/crank/dom.js' doesn't help.
If they’re changing stuff rapidly, I guess this could go in a later release when they figure it out. Not worth doing rollup hacks to figure it out today.
FWIW, I think the core issue on their end is still https://www.pika.dev/npm/snowpack/discuss/151 "Snowpack 2: Can't import subpackages"
But I _am_ able to successfully import 'preact/hooks', suggesting to me that a workaround is possible. I think it would require crank to publish a dom/package.json file and a dom/index.js.
https://github.com/preactjs/preact/commit/7d708e886adbb30b01374b8bcd648dbcc7f2c8e2
https://github.com/preactjs/preact/pull/2319
Just found this, maybe it’s relevant? What on Earth is up with the exports map? It feels like such a scary and dangerous configuration option.
What does "./": "./" do????? Jesus.
exports locks down all files that aren't explicitly exported. (IMO, this is a good thing; it ensures that internal files can't be used outside your package, so people can't depend on them and break during upgrades.)
I think the current iteration of Snowpack doesn't attempt to consume package.json via require; I think it just reaches into the ./node_modules folder and reads the file directly.
Yeah, I had it right. https://github.com/pikapkg/snowpack/blob/master/src/util.ts#L71
Fixing https://www.pika.dev/npm/snowpack/discuss/151 would require a PR to fix "resolveDependencyManifest" to handle subpackages
FWIW it seems like some of the fixes mentioned above have been merged and are available in the latest version of snowpack (2.9.0 as of this comment).
snowpack's module-discovery tool still doesn't find scoped packages, so I had to manually add @bikeshaving/crank and @bikeshaving/crank/dom to the install field of snowpack.config.js . but I did see a note in the docs that JSX is only supported out-of-the-box in files with the .jsx extension, and I was able to work around that by installing the @snowpack/plugin-babel and adding a babel.config.js to my repo.
I have a Snowpack template here which I’m experimenting with. No testing or hot reloading yet, but it seems to work fine.
Hot reloading should probably go in its own issue. My idea for how it should work is that we keep a global cache of function definitions by module and only redefine functions when their definitions change. I haven’t really been able to learn anything by reading the sources of the hot-reloading stuff by other frameworks; they very much feel like Rube Goldberg machines in terms of complexity. One limitation of Crank is that we don’t have any knowledge of the internal state of generator components, so we won’t be able to preserve the state of a component which is redefined. I don’t mind this limitation, personally, but YMMV.
Snowpack feels like the best in class of the current bundlers, but I’m still unhappy with all bundlers for the config file-based all-in-one builds plus dev server architectures they use. I’ve been working on a prototype bundler alternative but I’ve put it on pause because my dissatisfaction goes down to the level of runtimes (both Node and Deno are annoying me at this point).
Most helpful comment
FWIW it seems like some of the fixes mentioned above have been merged and are available in the latest version of snowpack (2.9.0 as of this comment).
snowpack's module-discovery tool still doesn't find scoped packages, so I had to manually add
@bikeshaving/crankand@bikeshaving/crank/domto theinstallfield of snowpack.config.js . but I did see a note in the docs that JSX is only supported out-of-the-box in files with the.jsxextension, and I was able to work around that by installing the@snowpack/plugin-babeland adding a babel.config.js to my repo.