Comments (8)
Hi Yang!
Thanks so much for your kind words about the jsxLoader I wrote; I really appreciate it!! π π
Also great job documenting the issue and creating the very clear test project. This makes it very easy for me to help with plus I can use it for new ideas to look up different debugging options.
For a quick background on how JSX is compiled to JS - in both Babel and jsxLoader each compiled JavaScript file or <script type="text/babel">
is appended as an inline <script>
element to the <head>
once it's compiled.
For Babel Standalone I see the latest versions are including an inline source map and I don't recall this with older versions of Babel so I'm going to research it more later this week or next week.
For jsxLoader the <script>
elements include a few data-*
attributes for debugging to show the original source of the compiled code and how it was compiled (IE, Older Chromium, Older Safari will use Babel Standalone).
Using this method the inline JavaScript doesn't show up for debugging in DevTools because it's added as a "VM" after the page is loaded; Chrome even assigns it "VM####" as the internal ID which shows in DevTools. The problem with "VM" scripts is that you can't easily set a breakpoint and when you do set one it only lasts as long as the page is open.
Originally when I tested this Babel Standalone worked when using React DevTools addon however based on your issue and the great demo project you created I see it now works in Chrome by default. I can speculate on several reasons but rather than guess I will do more testing Thu or Fri (or mostly likely next week). Also in the past I found Chrome had worked better for debugging errors than Firefox or other browsers but I haven't tested in a while so I'll test all the browsers again.
In the meantime here is a "hack" that can be used to debug the compiled JavaScript. Until you opened this issue I haven't even used this yet although I have had Chrome take me to errors at runtime but never was able to set a proper breakpoint before so thank you for your issue as it will help improve debugging with jsxLoader.
This demo is using the playground template: https://dataformsjs.com/en/playground
A version build with React and using the Monaco Editor (VS Code) is available here: https://dataformsjs.com/examples/code-playground-react.htm
The Monaco version allows for easier editing of JSX over CodeMirror and I intend on using it on the main site but haven't made the time yet.
On the main HTML page I added a simple function; this could have also been added on a linked JS file (not JSX).
In app.jsx
I call the debug function.
In DevTools I then set a breakpoint on the debug function and refreshed the page. Once the debugger was called I moved up the call stack to the previous function from the "VM" compiled JavaScript.
Then in the VM I was able to set a breakpoint on other parts of the code and once it was called Chrome stopped and allowed me to debug as expected. I will test Firefox and other browsers later to see how they handle it.
Related to this, an option is to keep complex logic (business rules, algorithms, etc) in a regular <script>
tag or JavaScript file and call the needed functions from JSX. Then Unit Testing and Debugging can happen with standard JavaScript while the UI is rendered from React and jsxLoader. If Unit Testing of the UI is needed I personally recommend using a headless browser (Puppeteer or Playwright) to test the compiled result with a real browser (I can make time to help with examples later if needed).
So that is a quick hack on how to debug. As I mentioned I am going to research this topic in more detail to see if there are better solutions available now. I'll let you know what I find and in the meantime if you have any questions feel free to ask and I'll be happy to help!
Best,
Conrad
from dataformsjs.
Thanks a ton, Conrad! Your help is beyond my imagination.
from dataformsjs.
Wow, thank you so much!
BTW do you happen to have any idea how to use JSX and ES module without build tool, see the question here: https://stackoverflow.com/questions/68648959/how-to-make-es6-modules-and-jsx-working-without-server-side-build
from dataformsjs.
Your welcome!
The issue with importing JSX using ES module syntax from a browser is that the browser only understands JavaScript and not JSX so to my knowledge there is no way of using the standard import test from './test.js'
syntax if using JSX. That said there are definitely ways to work around the issue but you have to get creative.
Alternatively if JavaScript functions or standard classes are used instead of JSX then import test from './test.js'
will work because the browser will understand ./test.js
.
The one way I've worked around the issue is I created a <LazyLoad>
component that dynamically downloads and compiles the JSX on first use. IMPORTANT - this component uses file name extensions so JSX files need to use *.jsx
rather than *.js
. The component supports *.jsx, *js, and *.css
files. The component itself has no dependancies outside of React (or Preact) and the jsxLoader so if needed it can easily be copied and modified for a project that has different but similar needs.
Documentation is here:
Docs contain several demos along with a link to the source code of LazyLoad
.
https://github.com/dataformsjs/dataformsjs/blob/master/docs/jsx-loader.md#code-splitting-%EF%B8%8F
Another example is on the Playground page: https://dataformsjs.com/en/playground
In app.jsx
you can see the source code for both the data page and calculator page are only loaded each link is clicked on because it uses LazyLoad
to download and compile the JSX file.
In the related calc-react.jsx
file you can see the export function Calculator
component which includes JSX. The data-react.jsx
page is similar in design for the core structure.
If you open the playground site from app-react.htm
and keep DevTools open with the Network tab you can see how LazyLoad
only downloads the JSX once. Also related to my previous comment once the JSX is downloaded and compiled you can view in a <script>
element that gets added to <head>
.
In an ideal situation we could perhaps specify rendering code for the native import
however that would only add additional complexity to browser API's so in the meantime unless a standard solution is developed I feel the LazyLoad
component works well. On the places demo (link below) you can see it's being used to dynamically load additional large JS and CSS files only if needed and only once the first time the page is accessed (example - specific city that shows a map).
https://dataformsjs.com/examples/places-demo-react.htm#/en/
from dataformsjs.
Hi Yang,
Here is a quick update on how debugging works with Babel. The scripts are loaded via the source mapping comment as shown in the image below.
I've done a little research so far but need to do a lot more which I'll do next week. In the meantime I would recommend setting a break point on a regular JavaScript function, calling that function from JSX then using the callstack to set breakpoints on other parts of the code.
I'll update you as I make progress or it it will take a long time to add. In the meantime let me know if you have any questions as I'm happy to help.
from dataformsjs.
Hi Yang,
Quick update as it's been over a week. I'm taking several vacation days this week so I likely won't be making any updates this week but soon I'll add new options to allow the jsxLoader to use Babel with Debugging and ideally debug without Babel.
In the meantime a good option is to use the JavaScript debugger
statement. I'll update docs later for this as well.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger
Personally I have rarely used this (if ever) so I forgot about it till now but it seems ideal for debugging JS code that is generated in the browser.
To use simply add a debugger;
line in the code. If DevTools is open then it will stop on the code just like if a breakpoint were manually set.
You could use it with logic as well:
if (condition) {
debugger;
}
Debugger Statement in Source Code
With DevTools it triggers a breakpoint in the generated code
from dataformsjs.
Hi Yang,
I just published a new release that includes the new property to help with debugging and gave you credit in the https://github.com/dataformsjs/dataformsjs/blob/master/CHANGELOG.md for opening this issue and helping improve the debug process with JSX Loader
Now by setting the following two properties on the latest build 5.10.0
debugging works (of course downloads Babel so you would want to turn it off after debugging). Later I'm going to update the main JSX Loader doc in more detail.
jsxLoader.isSupportedBrowser = false;
jsxLoader.sourceMaps = true;
In case you are curious the update needed to make this was relatively small:
4cb36c2
I have a some tips that can help you work with Preact + HTM if you need to include React Components compiled for React.
At the core level many published React Components will reference window.React
so simply setting window.React = window.preact;
after Preact is loaded and before other 3rd-party components can help solve many issues (this assumes no build process).
The JSX Loader has a function usePreact()
which you can see it. It makes additional changes in compiled code to help 3rd-party React Components work with Preact.
https://github.com/dataformsjs/dataformsjs/blob/master/js/react/jsxLoader.js#L214
One other related resource I've created is this: https://awesome-web-react.js.org/
It includes only one HTM demo (done with React) but the main thing is it shows how many published 3rd-party React Libraries can be used online without having to run a build. If you have any related questions I'm happy to help out.
Best,
Conrad
from dataformsjs.
Hi Conrad,
Thanks for the update, very appreciated. In the meantime, we discovered another approach with Preact + HTM. HTM string literals are like JSX but donβt need to compile. Nevertheless, thanks for your library, it works great with react without any build tool. :-)
Best, Yang
from dataformsjs.
Related Issues (9)
- remove hashtag from url? HOT 7
- Add Support for Vue 3 HOT 2
- Add an API to JSX Loader HOT 17
- react hooks support? HOT 3
- wrong compile result in jsx HOT 5
- jsxLoader: Less than operator assumed to be an open element HOT 3
- jsxLoader: Uncaught SyntaxError: Unexpected token ',' HOT 3
- Confusing documentation on use of import statement HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dataformsjs.