It has been quite and odyssey, trying to figure out which tools to use in the frontend for my project Gachou.
Preact CLI / Tailwind / Storybook
I started with
tailwind, and I wanted to use
developing components in isolation. Then I encountered…
Dependency conflicts with webpack!
Storybook uses a different webpack version than
preact-cli. Having both
libraries in the same project leads to fascinating problems, because they pull
in lots of different dependencies. Different versions of the same package. For
preact-cli dev-server suddenly failed with an error in the
Uncaught TypeError: AllHtmlEntities is not a constructor
This happens, because the package
html-entities is present in different
incompatible versions in the dependency tree.
> yarn why -R html-entities └─ gachou-web-ui@workspace:. ├─ @storybook/addon-docs@npm:6.4.8 [a3186] (via npm:^6.4.8 [a3186]) │ ├─ @storybook/builder-webpack4@npm:6.4.8 [9e85e] (via npm:6.4.8 [9e85e]) │ │ └─ webpack-hot-middleware@npm:2.25.1 (via npm:^2.25.1) │ │ └─ html-entities@npm:2.3.2 (via npm:^2.1.0) │ └─ ... ├─ ... └─ preact-cli@npm:3.3.2 [a3186] (via npm:^3.0.0 [a3186]) └─ webpack-dev-server@npm:3.11.3 [e4681] (via npm:^3.11.2 [e4681]) └─ html-entities@npm:1.4.0 (via npm:^1.3.1)
Package managers like npm and yarn solve such conflicts, by placing one library
in the root
node_modules directory, and another version inside the dependent
packages. In my case,
node_modules/html-entitieswas version 2.3.2
node_modules/webpack-dev-server/node_modules/html-entitieswas version 1.4.0
webpack-dev-server needs version 1.4.0, but that is not the version that
is injected in the page, because webpack looks for it in the uppermost
node_modules directory. That’s why, it uses version 2.3.2.
As workaround, I added some extra code to
- Search for
preact-clistarting in the project root.
- Search for
- Search for
- Add an
resolve.aliasto the config, providing the correct path.
This seemed to work at first, but I faced similar problems soon enough. In the
Webpack has a huge dependency tree, which greatly increases the probability for such problems.
But, what if I could have similar features with…
I decided to try wmr.dev, which is a new, advanced build
system for Preact based on Rollup. The great thing about
wmr is that it is
is also pretty fast, because it targets ESM modules and does not do any
bundling. The dev-server output looks almost like the original source-code, so
source-maps are not needed (according to the developers). I am not sure if this
is true, but my very simple tests worked very well.
But when I wanted to use
keycloak.js, it wasn’t working so well anymore. The
issue I was having with keycloak was similar to this
issue with node-html-parser. I
took away the impression:
wmr does not work well with common-js packages. But
to be honest: I cannot reproduce the problems right now. I may be wrong.
The bottom line is: Rather than diving into the bugs and trying to find out exactly how to solve them, I decided to test the next tool.
That tool was vite.js. It is a build-system developed by
Evan You, the author of
wmr it is based on Rollup, also targets
ESM modules. Non-ESM libraries are converted to ESM before loading processing
It does have dependencies, but I haven’t experienced any conflicts yet. And it
is just as fast as
wmr. Honestly, when I saw
vite I never wanted to return
I started using
vite with Preact and Tailwind. And tried to implement my first
user story: The Login.
As a user I want to be able to log in. And I want to be able to log out again. The logout button should be in a dropdown menu in the top-right corner of the page.
I could probably have implemented this dropdown myself. But I could also have
taken the easy way and used a component library like
Amazingly, Preact and
react-bootstrap seemed to work together. I hadn’t
expected this. But just when I started to become confident… TypeScript errors!
It had something to do with React-Portal, but I haven’t taken exact notes. I am sure there is a solution to it, but after all those trials-and-errors, I wasn’t in the mood of further investigation.
I abandoned Preact and switch to React, which I know well from work and which I could expect every React-library to work with.
I encountered one more issue with
vite: In our last projects at work, we used
openapi-client-axios to generated TypeScript types from the backend’s OpenAPI
I tried to use it with
vite, but got the following error:
Error: Build failed with 1 error: node_modules/@jsdevtools/ono/esm/types.js:1:9: ERROR: No matching export in “browser-external:util” for import “inspect”
I believe this is because
axios supports Node.js and browsers. There might be
some Node.js code mixed with browser-code. For some reason is no problem for
webpack, but when
vite tries to generate ESM-code from the
(common-js) code, it fails.
I didn’t dig deeper here, but simply chose a different library:
will integrate this library in a way that it is simple to replace, just in case.
My main takeaways from this odyssey are:
- Modern build tools like
viteare much faster than
webpack, especially when it comes to running dev-servers.
- Preact is a nice framework. Small. Looks solid. But React has a much larger community. A lot of libraries are developed for React. They may coincidentally work with Preact, but if you want to get something done fast and without much hassle, choose the original.
wmris and interesting, but
viteseems to be more mature.
As always, what you choose depends on your situation: How much pressure do you have? How large is the project? Can you try new things or do you have to play it safe?
I am going to take the safe road with Gachou. Not because I have external pressure, but I would like to see some results before the next photo-calendar is created… before next Christmas!