bikeshaving / crank

The Just JavaScript Framework
https://crank.js.org
MIT License
2.7k stars 75 forks source link

babel-preset-crank #66

Open ryhinchey opened 4 years ago

ryhinchey commented 4 years ago

I made a babel preset for crank so you don't have to type these two lines in every component you write:

/** @jsx createElement */
import {createElement} from "@bikeshaving/crank";

It works with webpack right now but for Parcel you'll need to upgrade to Parcel 2. There's an existing bug with JSX pragmas that won't get fixed until the next major version of parcel.

I'll close this issue in a day or two :)

brainkim commented 4 years ago

@ryhinchey Reopening this issue for visibility and also actionability. It could be nice to document it in the detailed getting started stuff (there’s an open PR for detailed getting started instructions that I still haven’t been able to review but have been meaning to get to). Thanks for working on this stuff! Sad that the actual babel plugins have names like plugin-transform-react-jsx 😕

brainkim commented 4 years ago

@ryhinchey Does this plugin automatically insert an import {createElement} from "@bikeshaving/crank";? I like the explicitness of having to import createElement yourself. Saw this error and was puzzled for a second:

> webpack

Hash: d500fe14b0213f3288d0
Version: webpack 4.34.0
Time: 398ms
Built at: 05/06/2020 1:50:40 AM
 1 asset
Entrypoint main = main.js
[0] ./src/main.jsx 433 bytes {0} [built] [failed] [1 error]

ERROR in ./src/main.jsx 2:9
Module parse failed: Identifier 'createElement' has already been declared (2:9)
File was processed with these loaders:
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
| import { createElement } from "@bikeshaving/crank";
> import { createElement } from "@bikeshaving/crank";
| import { renderer } from "@bikeshaving/crank/html";
| 
ryhinchey commented 4 years ago

Yah - that’s exactly what it does

ryhinchey commented 4 years ago

Technically this plugin does 2 things.

  1. Tell the Jsx plugin to use createElement instead of React.createElement (so you don’t need the pragma comment)
  2. Auto import createElement from Crank so it’s in scope

I think importing the createElement function by hand is annoying. I appreciate being explicit but find this instance of it unnecessary given most developers won’t actually use createElement in their code directly.

That said, this plugin could provide both options.

EDIT: there is an issue if someone imports createElement because they actually use it in their code. It probably is best to require the import now that I’m thinking about it more.

ryhinchey commented 4 years ago

Ok I just released 0.1.0 that removes the auto import of createElement so all this plugin does is remove the need for the /** @jsx createElement */ comments

brainkim commented 4 years ago

If there was logic which checked if it didn’t exist and imported it I wouldn’t mind that either!

ryhinchey commented 4 years ago

Yah maybe I’ll do that. Seems like too much logic for a super simple Babel plugin

jonrsawyer commented 4 years ago

Technically, it still does two things - it also adds '@babel/plugin-transform-react-jsx' to the list of Babel plugins. I realized that when I tried to remove it and go back to using the pragma comments - without them, the import of createElement is flagged as an unused import.

ryhinchey commented 4 years ago

@jonrsawyer you mean eslint is flagging createElement as an unused import right?

That’s to be expected and we need to have a crank eslint preset to turn that off or do it manually in your eslint config.

ryhinchey commented 4 years ago

I just updated this preset to also add import {createElement } from '@bikeshaving/crank' if it doesn't exist already in your file