Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSR: Could not resolve "@suid/material" when trying to bundle using ESBuild #186

Open
Bersaelor opened this issue Mar 3, 2023 · 2 comments
Labels
question Further information is requested

Comments

@Bersaelor
Copy link

Bersaelor commented Mar 3, 2023

Hello,

Attempt 1

so I have a working SSR solution, where I'm bundling up a solid.s build using aws sam. Internally aws sam builds each folder as a single module using esbuild.

I'm using rollup to bundle the solidjs site into a module, which can then be built by esbuild.

The intermediate result of the `rollup` looks like the following:
'use strict';

var web = require('solid-js/web');
var material = require('@suid/material');
var solidJs = require('solid-js');

const _tmpl$$4 = ["<div", " style=\"", "\">", "</div>"];
const GradientBack = props => {
  return web.ssr(_tmpl$$4, web.ssrHydrationKey(), "background:" + "linear-gradient(180.2deg, #4E6B76 0.14%, #94A6AC 99.8%), #FFFFFF" + (";flex:" + 1), web.escape(props.children));
};

// .. lots of bundled rolled up code

but when I try to build this with esbuild, I get:

Build Failed
Error: NodejsNpmEsbuildBuilder:EsbuildBundle ✘ [ERROR] Could not resolve "@suid/material"

    ssg/lib/index.js:5:23:
      5 │ var material = require('@suid/material');

Before I added @suid/material it still built fine and worked. I wonder if the error is because the node_modules/@suid folder looks so different (having an index.jsx file with all the exports) compared to the node_modules/solid-js folder. The solid-js folder has a package.json and a dist subfolder.


Attempt 2

Now, the above file is created by using rollup -c rollup.config.js on a pretty standard Solid-js setup.

`rollup.config.js`:
import jsx from 'acorn-jsx';
import nodeResolve from "@rollup/plugin-node-resolve";
import common from "@rollup/plugin-commonjs";
import babel from "@rollup/plugin-babel";

export default [
  {
    input: "index.jsx",
    output: [
      {
        dir: "lib",
        exports: "auto",
        format: "cjs"
      }
    ],
    external: ["solid-js", "solid-js/web", "@suid/material/styles", "@suid/material"],
    acornInjectPlugins: [jsx()],
    plugins: [
      nodeResolve({ preferBuiltins: true, exportConditions: ["solid", "node"] }),
      babel({
        babelHelpers: "bundled",
        presets: [["solid", { generate: "ssr", hydratable: true }]]
      }),
      common()
    ]
  }
];

One alternative idea I had was to not declare @suid external and roll up it up with the rest, i.e. only

    external: ["solid-js", "solid-js/web"],

When I do this, the rollup -c rollup.config.js fails on importing ./styles:

[!] Error: Could not resolve './styles' from ../site/node_modules/@suid/material/useMediaQuery.js
Error: Could not resolve './styles' from ../site/node_modules/@suid/material/useMediaQuery.js
    at error (/../rollup/dist/shared/rollup.js:198:30)
    at ...
error Command failed with exit code 1.

which is caused by

import { useTheme } from "./styles";

being the first line in useMediaQuery.js.

Now I'm not an expert in how node imports modules, so I'm kind of lost of what I could do to get suid imported into my project.

@Bersaelor
Copy link
Author

Bersaelor commented Mar 3, 2023

PS: Now, as for Attempt 2 above, if I rename all *.jsx to *.js , i.e. running:

for x in node_modules/@suid/**/*.jsx; do mv \"$x\" \"${x%.jsx}.js\"; done

on the node_modules before the second approach above, I actually can get rid of a lot of the import-problems.

To be fair, for some reason the global rename command above takes 20s to run, not great for building new site versions.

So yeah, if I rename allt he jsx to js I can build a valid bundle for SSR. Unfortunately it'll now fail during normal vite development work.

@Bersaelor Bersaelor changed the title Could not resolve "@suid/material" when trying to bundle using ESBuild SSR: Could not resolve "@suid/material" when trying to bundle using ESBuild Mar 3, 2023
@juanrgm
Copy link
Member

juanrgm commented Mar 8, 2023

The current module system (ESM/CommonJS) is insane and I had a lot of trouble finding a balance.

There may be changes in the future but I have not decided yet due to the problems they present. I'll wait for TypeScript 5 with its new module resolutions to see how it goes.

The main reason for the current distribution file structure (https://www.npmjs.com/package/@suid/material?activeTab=explore) is to favor direct import (no dist folder involved). Yes tree shaking exists, but it's useless when you're developing, as it involves scanning the entire file (imagine that with @suid/icons-material). That's why @suid/vite-plugin optimizes imports.

Specifying the available imports in the package.json file is the right way to go, but last time I tried it the TypeScript integration was a disaster (IntelliSense).

In summary, the specifications of how to distribute the packages should comply with the following:

  1. Direct imports (import Box from "@suid/material/Box").
  2. Imports via index (import { Box } from "@suid/material").
  3. Avoid having to add the file extension on all imports into the SUID repository (ex: import "./file.jsx").
  4. Avoid dual packages (ESM/CommonJS) or bundling that increase package size.
  5. Of course, auto-suggestion on all imports with named specifiers in VSCode and typing of direct imports.
  6. Avoid leaving K.O. to vite with imports through the index.

@juanrgm juanrgm added the question Further information is requested label Mar 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants