Skip to content

IE11 compatibility#1006

Merged
Marc-Andre-Rivet merged 23 commits intodevfrom
1003-dash-ie11
Nov 14, 2019
Merged

IE11 compatibility#1006
Marc-Andre-Rivet merged 23 commits intodevfrom
1003-dash-ie11

Conversation

@Marc-Andre-Rivet
Copy link
Copy Markdown
Contributor

@Marc-Andre-Rivet Marc-Andre-Rivet commented Nov 7, 2019

Related to #1003 and actually solves the issue with additional PRs (will be linked)

Also fixes #1011.

repo pr
dash-table plotly/dash-table#637
dash-core-components plotly/dash-core-components#696
dash-html-components plotly/dash-html-components#143
dash-bio plotly/dash-bio#437
dash-canvas plotly/dash-canvas#29
dash-cytoscape plotly/dash-cytoscape#75
dash-daq plotly/dash-daq#73

The latest async changes and following tests uncovered that Dash is broken for IE11 / Edge < 15. This comes from many things:

  1. @plotly/dash-component-plugins was not transpiled when used in projects
  2. @plolty/webpack-dash-dynamic-import was not ES5 (can't be transpiled, because added directly to the webpack artifact)
  3. Multiple projects were not using core-js or @babel/polyfill. Even with correctly transpiled code they would not have worked
  4. Multiple projects depend on npm dependencies that either (1) have source code as the main in package.json -- combined with standard webpack settings excluding node_modules this caused this code not to be transpiled, or (2) transpiled npm resources not transpiled in ES5, or (3) npm resources with dist but with main still pointing to the source

Handling source code from 3rd parties as part of your build process is complicated.. maybe your configuration is not compatible, or maybe the code uses another scheme (e.g. import/export vs. required vs. module.exports). The module.exports case turned out to be problematic for certain 3rd parties because of core-js+useBuiltIns: usage side-effects, namely,the code evals everything to commonjs, wrapping module.exports in a particular way that is almost but not quite normal module.exports usage in Node.

This PR and the attached PRs solves all of the above in 3 ways.

  1. The artifacts are now ES5-validated with es-check, making it impossible to get a successful build with hanging ES6+ syntax
  2. The polyfills have been moved into the renderer -- they are now shared like react, react-dom, and prop-types -- this removes the responsibility from the component developer's hands.. making for less chances of mistakes.. a component developer can still continue using their own polyfills if some additional specifics are needed
  3. npm resources that are not ES5 compatible are now transpiled either from source code or from the dist (or whatever) artifact -- this is time consuming as the webpack exclude needs to be tweaked manually (this is mostly not an issue) -- or a alias is provided to use a dist instead of the source if the project was not setup correctly..

Not covered here is whether the code actually runs in IE11 / Edge < 15, but it establishes a good baseline with rapid (build-time) feedback. Further steps would involve setting up a test environment on (say) the docs with IE11 or the oldest version of Edge available.


Also, this version of Dash will become the minimal version required for all components that are dropping @babel/polyfill or core-js from their build -- effectively, will make this version of Dash the minimal version for all core repos, bio, canvas, cytoscape, daq.

Interesting side-effect, externalizing polyfills will reduce the JS size for core (renderer, html, dcc, table) by about 70kB and the externalized polyfill can be cached / will probably be stable through multiple releases or 7% of the current minimal JS load.


Other PRs will need to update @plotly/webpack-dash-dynamic-import to 1.1.3 when approved / published and some will require a version bump.

Marc-André Rivet added 3 commits November 7, 2019 09:48
- make webpack-dash-dynamic-import es5
- no polyfills in build
{
"name": "@plotly/webpack-dash-dynamic-import",
"version": "1.1.2",
"version": "1.1.3",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Need a new version. The other PRs are using a rc release 1.1.3-rc1

const srcFragments = src.split('/');
const fileFragments = srcFragments.slice(-1)[0].split('.');
var srcFragments = src.split('/');
var fileFragments = srcFragments.slice(-1)[0].split('.');
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Use only ES5 syntax. This will be validated in the end by es-check

corejs: 3
}], '@babel/preset-react'],
presets: [
'@babel/preset-env',
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The polyfills are externalized. We only use preset-env to know what the transpilation target is.

"prop-types@$proptypes.min.js",
],
"dev": [
"polyfill@$polyfill.min.js",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Externalized polyfills, to be used by all components

"build:dev": "webpack --build local",
"build:local": "renderer build local",
"build": "renderer build",
"postbuild": "es-check es5 dash_renderer/*.js",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

postbuild check, automagically runs after build

{
test: /\.js$/,
exclude: /node_modules/,
exclude: /node_modules\/(?!@plotly\/dash-component-plugins\/|uniqid\/|check-prop-types\/)/,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Exclude all that can be excluded. In this case it means that @plotly/dash-component-plugins, uniqid and check-propstypes` need to be transpiled to the correct target b/c we're using the source or a dist with a less stringent target.

}
for name, subfolder, filename, target in self.deps_info:
version = self.deps[name]["version"]
for scope, name, subfolder, filename, target in self.deps_info:
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Handle scoped packages with @SCOPE/NAME format

("react-dom", "umd", "react-dom.development.js", None),
("prop-types", None, "prop-types.min.js", None),
("prop-types", None, "prop-types.js", None),
("@babel", "polyfill", "dist", "polyfill.min.js", None),
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Add polyfill, add None scope for all other deps

@Marc-Andre-Rivet Marc-Andre-Rivet changed the title 1003 dash ie11 IE11 compatibility Nov 7, 2019
@@ -0,0 +1 @@
import '@babel/polyfill'; No newline at end of file
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

jest now needs the polyfills..

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

seems fine, but I'm surprised jest is running in an environment that needs polyfills.

Copy link
Copy Markdown
Contributor Author

@Marc-Andre-Rivet Marc-Andre-Rivet Nov 8, 2019

Choose a reason for hiding this comment

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

rephrasing: jest needs the polyfills to handle our code!

Copy link
Copy Markdown
Collaborator

@alexcjohnson alexcjohnson left a comment

Choose a reason for hiding this comment

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

💃 This all looks good. Now to the ⛰ of other PRs...

- bump usage / remove from webpack exclusion override
{
test: /\.js$/,
exclude: /node_modules\/(?!@plotly\/dash-component-plugins\/|uniqid\/|check-prop-types\/)/,
exclude: /node_modules\/(?!uniqid\/|check-prop-types\/)/,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

😍

jsonpScriptSrc = function(chunkId) {
let script = getCurrentScript();
let isLocal = isLocalScript(script);
if (typeof jsonpScriptSrc !== 'undefined') {
Copy link
Copy Markdown
Contributor Author

@Marc-Andre-Rivet Marc-Andre-Rivet Nov 8, 2019

Choose a reason for hiding this comment

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

jsonpScriptSrc is not defined if there are no async resources, the typeof ... === 'undefined' check is the only way in JS to test for the existence/non-existence of a variable in a safe way.

this.setProps = this.setProps.bind(this);
}

setProps(newProps) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We were creating new setProps on each TreeContainer render. Everything in here is dependent on the injected props, it can be reused if the instance is reused. Should reduce the number of re-renders, if nothing else.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🎉


/**
* This code is injected as-is in the webpack artifact and must be ES5 compatible to work in all scenarios.
* This will not get transpiled.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Just to note, because I was curious: it doesn't get transpiled, but it does get minified in the pipeline you've got set up - as we would hope 🎉

@Marc-Andre-Rivet Marc-Andre-Rivet merged commit 771152a into dev Nov 14, 2019
@Marc-Andre-Rivet Marc-Andre-Rivet deleted the 1003-dash-ie11 branch November 14, 2019 14:54
@Marc-Andre-Rivet Marc-Andre-Rivet added this to the Dash v1.7 milestone Nov 15, 2019
@rpkyle rpkyle restored the 1003-dash-ie11 branch December 25, 2019 04:29
@alexcjohnson alexcjohnson deleted the 1003-dash-ie11 branch July 28, 2021 17:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Renderer TreeContainer setProps value is change on each render

3 participants