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

Playground and development environment fixes for Lerna #1642

Merged
merged 33 commits into from Mar 16, 2020

Conversation

epicfaace
Copy link
Member

@epicfaace epicfaace commented Mar 10, 2020

Reasons for making this change

Building off of work done in #1606 and #1641.

  • Update build and dev process and documentation (as discussed in Troubles with the new Playground #1630 (comment)). The developer will just need to run lerna bootstrap, run npm start from the package they are modifying, then run the playground from packages/playground to get a live-reloading playground.
  • Fix deploy previews by configuring netlify so that it runs lerna bootstrap, thus linking the packages with the local changes in the PR, before building the playground.
  • Export typings from @rjsf/core (fixes Export typings from @rjsf/core #1583) -- did this in this PR so that @rjsf/material-ui would work as well.
  • Fix playground issues in which the material-ui playground did not use the right ObjectFieldTemplate or ArrayFieldTemplate.

Fixes #1630 .

Checklist

  • I'm updating documentation
  • I'm adding or updating code
    • I've added and/or updated tests
    • I've updated docs if needed
  • I'm adding a new feature
    • I've updated the playground with an example use of the feature

@epicfaace epicfaace changed the title Playground fix 2 Playground and development environment fixes Mar 10, 2020
@epicfaace epicfaace changed the title Playground and development environment fixes Playground and development environment fixes for Lerna Mar 10, 2020
Copy link
Contributor

@Saulzi Saulzi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have not tried this out but many of the changes are similar to what I have done, please note that the CI still seems to be broken and I have a query with regards to UMD support

Comment on lines 6 to 8
"build": "npm run build:cjs && npm run build:es",
"build:cjs": "NODE_ENV=production BABEL_ENV=cjs babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./dist/cjs",
"build:es": "NODE_ENV=production BABEL_ENV=es babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./dist/es",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why no umd, is there still a umd build? as this is what I am using! basically I include the whole lib and allow other plugins to use version pulled in via umd with requirejs, potentually umd works with both commonjs loaders, iife i.e. the browser straight and AMD loaders

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, any thoughts @chanceaclark ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we might have to change build tools then. babel has a plugin for converting to UMD but it's kind of a all or nothing approach.

@Saulzi, if you mention umd works with commonjs (cjs) loaders, couldn't you just load in the cjs modules?

In the meantime, play around with using rollup and try to push a commit.

Copy link
Contributor

@Saulzi Saulzi Mar 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it works with both commonjs and AMD loaders please refer to https://www.davidbcalhoun.com/2014/what-is-amd-commonjs-and-umd/
https://riptutorial.com/javascript/example/16339/universal-module-definition--umd-
https://www.google.com/search?q=common+javascript+modules&oq=common+javascript+modules&aqs=chrome..69i57.11167j0j7&sourceid=chrome&ie=UTF-8

AMD has been around for some time before the ES6 (ESM) standard.. i.e. dojo framework had amd support in around since 2011, many javascript developers have used things such as jquery etc which have used this pattern for some time and not even realised.. for example react builds to a umd module other popular javascript frameworks such as leaflet, moment, knockout and chart.js are built to umd modules.

@chanceaclark @epicfaace from experience rollup will make porting to typescript much easier as it is quite easy to build a and export ESM / UMD with rollup and typescript (whack it through the terser plugin for release builds) ,

Do you plan on just typescripts JSX/ES5 support rather than the current babel configuration. one thing to note is that if you plan to use babel to transpile typescript, this is bit behind the current typescript release for example it does not support newer syntax such as import type {} from "module" in ts.

In my mind webpack and browserify should be taken out back and shot (have you ever seen the intro to stealjs video), crazy amount of configuration etc and the whole node_modules black hole. I will say that steal is good for sites but not libs and another potential is parcel although I think this is aimed more at applications rather than libs)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated it to use the old webpack config to create the UMD build again. We can definitely switch to rollup but for now I'm just adding the old webpack config which works and won't affect local development.

"build": "npm run build:cjs && npm run build:es && npm run build:es:lib",
"build:cjs": "NODE_ENV=production BABEL_ENV=cjs babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./dist/cjs",
"build:es": "NODE_ENV=production BABEL_ENV=es babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./dist/es",
"build:es:lib": "NODE_ENV=production BABEL_ENV=es babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./lib",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chanceaclark I had to add this line in because we needed to import things like @rjsf/core/lib/utils

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will check that I still get a UMD Module, this is vital for me and perhaps other users... essentially I pull this from the build output

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@epicfaace I'm guessing that's to keep support for it. What's to stop people from using doing this now:

import { deepEquals } from '@rjsf/core/dist/utils';`

IMO, it makes more sense to export the utils along with package or creating a utils package if you want to separate it.

Also, you are probably aware, but keep in mind this is still part of the alpha major version so there is more freedom in introducing breaking changes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good point. It seems like react-jsonschema-form/lib/utils is already used, though, see material-ui (https://github.com/rjsf-team/react-jsonschema-form/pull/1642/files#diff-92ef0ee17db18857941b12442a459de0R6) or #1643

Additionally, the documentation even has an example of using an actual component from the lib directory (https://github.com/rjsf-team/react-jsonschema-form/pull/1642/files#diff-443373237a67e0fe395c3da27e3595ebR553).

import SchemaField from "@rjsf/core/lib/components/fields/SchemaField";

This is probably bad, as we probably don't want to constrain ourselves with file structure. However, it would also be useful for users to be able to access the default fields / widgets. Perhaps it would be best to just make a @rjsf/utils package and expose fields through @rjsf/core/fields and widgets through @rjsf/core/widgets?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I say we break out the utils package since it'll be better to maintain that way. If we need to make a path or minor to the utils package, in theory it shouldn't break anyones installs if they are using a ^ (i.e. "@rjsf/utils": "^X.X.X").

For the fields and widgets, they should probably just be exposed in the root index file still so you can import them like so:

import { ArrayField } from '@rjsf/core';`

We would just need to ensure tree shaking is set up correctly, that way they don't import everything from @rjsf/core.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, sounds good. Let's do that in another issue / PR.

@epicfaace
Copy link
Member Author

this is now ready for review and CI is passing - @erunion @chanceaclark @Saulzi

Copy link
Contributor

@Saulzi Saulzi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not build on windows NODE_ENV issues.

Please see my other comments,

@epicfaace you are soooo close to the prize

netlify.toml Outdated
command = "npm run build:playground"
base = ""
publish = "packages/playground/build"
command = "npm run bootstrap && (npm run build || { sleep 120; false; })"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the sleep still needed here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No

"build": "npm run build:cjs && npm run build:es && npm run build:es:lib",
"build:cjs": "NODE_ENV=production BABEL_ENV=cjs babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./dist/cjs",
"build:es": "NODE_ENV=production BABEL_ENV=es babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./dist/es",
"build:es:lib": "NODE_ENV=production BABEL_ENV=es babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./lib",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will check that I still get a UMD Module, this is vital for me and perhaps other users... essentially I pull this from the build output

packages/core/package.json Show resolved Hide resolved
Comment on lines -14 to -37
function deepEquals(a, b, ca = [], cb = []) {
// Partially extracted from node-deeper and adapted to exclude comparison
// checks for functions.
// https://github.com/othiym23/node-deeper
if (a === b) {
return true;
} else if (typeof a === "function" || typeof b === "function") {
// Assume all functions are equivalent
// see https://github.com/mozilla-services/react-jsonschema-form/issues/255
return true;
} else if (typeof a !== "object" || typeof b !== "object") {
return false;
} else if (a === null || b === null) {
return false;
} else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime();
} else if (a instanceof RegExp && b instanceof RegExp) {
return (
a.source === b.source &&
a.global === b.global &&
a.multiline === b.multiline &&
a.lastIndex === b.lastIndex &&
a.ignoreCase === b.ignoreCase
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are some of these functions common i.e. do we have deep equality in the lib etc?

happy but DRY?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pointed out that there is a bug in this: #1438 (comment)

We still need to support this function until we can really refactor using an external lib. My recommendation is to convert everything to TS before we can tackle this.

Comment on lines 7 to 9
"build:cjs": "NODE_ENV=production BABEL_ENV=cjs babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./dist/cjs",
"build:es": "NODE_ENV=production BABEL_ENV=es babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./dist/es",
"build:es:lib": "NODE_ENV=production BABEL_ENV=es babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./lib",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NODE_ENV stuff here seems to not work on windows

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please see my other comments relating to UMD builds here, as this currently won't build for me I cannot check but basically need output as per UMD (this is commonjs iffe and amd all in one)

i.e..

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['exports', 'b'], factory);
    } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
        // CommonJS
        factory(exports, require('b'));
    } else {
        // Browser globals
        factory((root.commonJsStrict = {}), root.b);
    }
}(this, function (exports, b) {
    //use b in some fashion.

    // attach properties to the exports object to define
    // the exported module properties.
    exports.action = function () {};
}));

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this basically needs cross-env to be stuck in front in package.json's.. already there in other places.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note that this change in package.json to build both commonjs and esm really breaks things for me, basically there was one output before which was an amd module i.e. in the dist folder which I would dump with all my other js files

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note this now dumps lots of small files and not a single minified / bundled file

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Saulzi can you share some example code that relies on the UMD build? That way I can make sure that the way it outputs will work with that code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this basically needs cross-env to be stuck in front in package.json's.. already there in other places.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Saulzi can you share some example code that relies on the UMD build? That way I can make sure that the way it outputs will work with that code.

@epicfaace @chanceaclark

https://github.com/Saulzi/react-jsonschema-form/tree/amd-example
Here is an example of using react-jsonschema-form via UMD. using all three legacy module loader types across node, and the browser.

I found a few things i.e. synthetic defaults etc with the current build...

Why build commonjs when UMD does it all for legacy module loaders.. essentially newer build tools such as rollup / webpack use ESM, node is stuck using commonjs and browser can essentually do amd (via steal / require / dojo / curl?), commonjs (stealjs), umd script tags and esm modules..

things would be so much better if react was built to esm module because then it would play nicer with rollup etc and would allow me to load it via script type module rather than relying on AMD.

I am glad this commit is now in merged as its definitely an improvement but still needs a little bit of tweaking, @epicfaace does this also resolve issues with CI i.e. is the playground preview now up to date?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Saulzi
You said "I found a few things i.e. synthetic defaults etc with the current build..." -- did you mean that you are able to use the UMD version now or are there still issues?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@epicfaace it does work but really when referencing this in the browser and via amd you shouldn't have to use .default... it is basically because of synthetic exports.

@@ -3,32 +3,34 @@
"version": "2.0.0-alpha.2",
"description": "A simple React component capable of building HTML forms out of a JSON schema.",
"scripts": {
"build:lib": "rimraf lib && cross-env NODE_ENV=production babel -d lib/ src/",
"build:dist": "rimraf dist && cross-env NODE_ENV=production webpack --config webpack.config.dist.js",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line used to cause a umd module

@epicfaace
Copy link
Member Author

ready for additional review @chanceaclark @Saulzi

"eslint --fix",
"prettier --write",
"git add"
]
},
"main": "lib/index.js",
"main": "dist/cjs/index.js",
"module": "dist/es/index.js",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to add this instead of including it in the files array.

Suggested change
"module": "dist/es/index.js",
"module": "dist/es/index.js",
"typings": "index.d.ts"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

"files": [
"dist",
"lib"
"index.d.ts"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove from above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines +6 to +10
"build": "npm run dist:build:umd && npm run build:cjs && npm run build:es && npm run dist:build:es:lib",
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./dist/cjs",
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./dist/es",
"dist:build:es:lib": "cross-env NODE_ENV=production BABEL_ENV=es babel --extensions \".js,.jsx,.ts,.tsx\" ./src --out-dir ./lib",
"dist:build:umd": "rimraf dist && cross-env NODE_ENV=production BABEL_ENV=umd webpack --config webpack.config.dist.js",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes. But we'll figure it out.

package.json Outdated
@@ -1,5 +1,5 @@
{
"name": "react-jsonschema-form",
"name": "@rjsf/core",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably don't want to change this. It should be the name of the repo if it's a monorepo.

Suggested change
"name": "@rjsf/core",
"name": "react-jsonschema-form",

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think should be done with the version attribute? I don't think Lerna automatically bumped it upon release, and I'm not sure if version is even relevant in the top of the monorepo.

@@ -5,8 +5,8 @@ import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';
import InputLabel from '@material-ui/core/InputLabel';

// import { WidgetProps } from 'react-jsonschema-form';
import { asNumber, guessType } from 'react-jsonschema-form/lib/utils';
// import { WidgetProps } from '@rjsf/core';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to remove this comment

Copy link
Contributor

@chanceaclark chanceaclark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@epicfaace
Copy link
Member Author

epicfaace commented Mar 16, 2020

I wonder whether it might be better to move playground from packages/playground to the root-level directory (playground) -- because I don't think we'll ever be publishing it as a package?

edit: Actually, I think it's fine -- keeping it under packages makes the root directory's package.json cleaner so you don't necessarily have to install playground dependencies just to get started. And it's already a private package so it won't be published.

@chanceaclark
Copy link
Contributor

I wonder whether it might be better to move playground from packages/playground to the root-level directory (playground) -- because I don't think we'll ever be publishing it as a package?

You won't be able to link @rjsf/core and the material-ui packages if we do. As long as there is a "private": true key/value in the package.json, it won't get published at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
V2
  
Done
Development

Successfully merging this pull request may close these issues.

Troubles with the new Playground Export typings from @rjsf/core
3 participants