Crank: Crank not installing correctly on Snowpack 2

Created on 7 May 2020  Â·  15Comments  Â·  Source: bikeshaving/crank

I managed to get Babel/JSX working on Snowpack, with a number of bug workarounds.

Here are the Snowpack bugs:

  1. Snowpack can run Babel with a plugin, but you also have to define a dummy "build:" step or it refuses to build anything. (Fix merged but not yet released)
  2. Despite the documentation, the Snowpack Babel plugin is "@snowpack/plugin-babel" and not just "babel" (Documentation fix merged but not yet deployed)
  3. JSX _must_ appear in a file with extension .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
bug help wanted

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/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.

All 15 comments

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

See my post on the create-crank-app issue on approach to get Snowpack working with TSX (no babel) with this gist...HMR does not work yet.

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).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lazeebee picture lazeebee  Â·  5Comments

dfabulich picture dfabulich  Â·  4Comments

mcjazzyfunky picture mcjazzyfunky  Â·  5Comments

GormanFletcher picture GormanFletcher  Â·  3Comments

workingjubilee picture workingjubilee  Â·  6Comments