lumeland / lume

🔥 Static site generator for Deno 🦕
https://lume.land
MIT License
1.83k stars 83 forks source link

How to use the non-minified dev environment in client side react, to get full error messages ? #400

Closed max-l closed 1 year ago

max-l commented 1 year ago

I followed this example to have client side react code in a project: https://github.com/lumeland/react-todo

And I am getting "minified" react errors, that suggest using a non minified build, to get full error and warning messages.

Uncaught Error: Minified React error #423; visit https://reactjs.org/docs/error-decoder.html?invariant=423 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.

I'm not sure if it's a setting in esbuild, an environement variable, linking to another react build, etc...

oscarotero commented 1 year ago

I just tried this configuration to use the development build:

site.use(esbuild({
    extensions: [".jsx"],
    options: {
      jsxDev: true, // To use jsx-dev-runtime
      minify: false, // To don't minify the javascript code
    }
}))

But I keep seeing this message. So not sure if I should do something else. I'm not a React expert.

max-l commented 1 year ago

Hmm, this kind of problem is hard to google, the search terms "minify", "dev mode", etc, have zillions of hits that don't address the topic.

Deno is doing some magic to fetch dependencies with this kind of syntax:

import React from "npm:react";

The solution is probably to use a development build :

https://unpkg.com/browse/react@18.2.0/umd/

react.development.js    110 kB  application/javascript
react.production.min.js 10.7 kB application/javascript
react.profiling.min.js  10.7 kB application/javascript

The challenge for me is to figure out how to get deno to load a dev build. I'm sure it's simple, once you know how to.

oscarotero commented 1 year ago

The client side javascript is not generated by Deno but esbuild plugin. There's a loader to resolve all imports. For npm modules, it uses esm.sh: https://github.com/lumeland/lume/blob/master/plugins/esbuild.ts#L91-L96

I used console.log to debug what URL are loaded and with jsxDev option to true, the Reac file is https://esm.sh/react@18.2.0/jsx-dev-runtime (which seems correct).

So I don't know where these warnings come from. Maybe from react-dom?

max-l commented 1 year ago

https://esm.sh/#docs

Development Mode

import React from "https://esm.sh/react?dev" With the ?dev option, esm.sh builds a module with process.env.NODE_ENV set to "development" or based on the condition development in the exports field of package.json. This is useful for libraries that have different behavior in development and production. For example, React will use a different warning message in development mode.

I tried this :

import { useEffect, useState } from "npm:react?dev"

and also this in import_map.json :

{
  "imports": {
    "lume/": "https://deno.land/x/lume@v1.16.0/",
    "react": "https://esm.sh/react?dev"
  }
}

And got errors in both cases

oscarotero commented 1 year ago

Oh, I didn't know the ?dev parameter. That's much better. It must be added not only to react but react-dom. I think this option should be managed by the esbuild plugin. For example:

site.use(esbuild({
    extensions: [".jsx"],
    dev: true
  }))

I'm going to make some changes. Just a second.

oscarotero commented 1 year ago

Ok, I just made some changes. The esbuild plugin has the esm option to configure the parameters to esm.sh.

site.use(esbuild({
    extensions: [".jsx"],
    esm: {
      dev: true,
      cjsExports: {
        "react-table": "useTable",
      }
    },
}))

If dev is true the ?dev option is included in all requests to esm.sh. This fixes the problem to switch to development or production environments.

The cjsExports object contain the names exported by the modules. In this example, the code: import { useTable } from 'npm:react-table' will download the package as https://esm.sh/react-table?dev=true&cjs-exports=useTable.

To try this, run deno task lume upgrade --dev.

max-l commented 1 year ago

I have tried this and had a problem, you can see it in this repo : https://github.com/max-l/lume-cjs-exports-test-case

The error message is : Caused by TypeError: Relative import path "react" not prefixed with / or ./ or ../ and not in import map from "file:///tmp/lume-cjs-exports-test-case/app/ProteinTable.jsx"

In the code, the prefix "npm:" is there:

import { useCallback, useMemo, useState, useEffect, Fragment } from "npm:react";

I tried both:

  "react-table": "useTable,useExpanded"
  "react-table": ["useTable", "useExpanded"]