Can I make Reason+React import react module from CDN? - reactjs

Building a component with Reason and React always gives me an module import statement for "react", which cannot be found if React is included from a CDN. Is there a solution for this? I've tried to define window.react = React in index.html without success. es6-global setting does not change anything.
I'm not using a bundling program like webpack.
Edit: Possibly relevant thread from Reason forum: https://reasonml.chat/t/can-one-load-reasonml-es6-modules-without-a-bundler/2219
Similar issue (not resolved): can one load reasonml es6 modules without a bundler
importmap (not yet implemented in browsers) could be another solution for this: Using ES6 Modules without a Transpiler/Bundler step

Technically, yes you can, but it's not going to be as easy as going with the npm flow and using a bundler.
The ReasonReact bindings are written in a way that produces output JavaScript that imports modules like:
import * as React from "react";
(If using ES6 module style.)
If using a CDN you would probably want an output that looks like this:
import * as React from "https://some.cdn/react";
The syntax (from the ReasonReact repo) that controls the output JS is:
[#bs.module "react"]
external createElement: (component('props), 'props) => element = "createElement";
If you changed it to:
[#bs.module "https://some.cdn/react"]
external createElement: (component('props), 'props) => element = "createElement";
...then you'd get the desired output. But the problem is then you need to change the sources ... i.e. maintain or find forked bindings for React for that CDN. Or set up some code automation that does a find-and-replace of [#bs.module "react"] with [#bs.module "https://some.cnd/react"]. So either way, it's not as simple as using a bundler.

Related

Can I use a compiled ReasonReact component together with the CDN version of React? [duplicate]

Building a component with Reason and React always gives me an module import statement for "react", which cannot be found if React is included from a CDN. Is there a solution for this? I've tried to define window.react = React in index.html without success. es6-global setting does not change anything.
I'm not using a bundling program like webpack.
Edit: Possibly relevant thread from Reason forum: https://reasonml.chat/t/can-one-load-reasonml-es6-modules-without-a-bundler/2219
Similar issue (not resolved): can one load reasonml es6 modules without a bundler
importmap (not yet implemented in browsers) could be another solution for this: Using ES6 Modules without a Transpiler/Bundler step
Technically, yes you can, but it's not going to be as easy as going with the npm flow and using a bundler.
The ReasonReact bindings are written in a way that produces output JavaScript that imports modules like:
import * as React from "react";
(If using ES6 module style.)
If using a CDN you would probably want an output that looks like this:
import * as React from "https://some.cdn/react";
The syntax (from the ReasonReact repo) that controls the output JS is:
[#bs.module "react"]
external createElement: (component('props), 'props) => element = "createElement";
If you changed it to:
[#bs.module "https://some.cdn/react"]
external createElement: (component('props), 'props) => element = "createElement";
...then you'd get the desired output. But the problem is then you need to change the sources ... i.e. maintain or find forked bindings for React for that CDN. Or set up some code automation that does a find-and-replace of [#bs.module "react"] with [#bs.module "https://some.cnd/react"]. So either way, it's not as simple as using a bundler.

How to remove dead code in Create React App

I have a create-react-app project, and I am working on reducing my bundled JS file size. About half of my bundle size is coming from a dependency called MDBReact (a react component library), and majority of it is not being used. I am trying to find out how/if I can remove dead code with tree shaking from the bundled build. I have been looking into this for a while and the closest article I found was this. This article leaves me confused and it does not give any explanation into how or if it can be done. I also found this guide on webpack tree shaking explaining how it can be done, but this does not seem to solve the problem.
CRA is using webpack to bundle code. Webpack can only treeshake es modules by default and commonjs modules when using plugins.
To help you on the way, how are you currently importing from MDBReact?
It looks like MDBReact is not written in es modules and webpack is therefore going to have a hard time tree shaking if you use the following import statement:
import { module } from 'MDBReact';
Instead you could try to import using the following
import modules from 'MDBReact/module';
You might have to change the path to the module depending on how MDBReact is structured. Take a look in the node_modules folder to find out.

Webpack requires file extension for react components

I'm trying to use Webpack in my React project using VS Code and running into an issue because webpack is now requiring the file extensions for my components.
For example, webpack tells me that it's unable to resolve the following component:
import MyComponent from '../components/Component123';
If I change it to the following by adding the file extension, it works fine:
import MyComponent from '../components/Component123.jsx';
I've never had this before and it's not even the conventional norm. What's causing this and how do I fix it?
BTW, my webpack version is 2.6.1.

Webpack: How can I combine two completely separate bundles using dynamic bundling

I have spent a lot of time looking into this, but to no avail. I am aware of how code splitting and dynamic bundling works in Webpack using the import promise API.
Howevr, my use case is that I have two completely separate bundles, generated separately using different webpack builds. To give you perspective, I am building React components and there is a requirement to dynamically load a react component into the page that has been compiled in a different process. Is this possible in react? I do have control over both webpack builds, so I can exclude dependencies, etc.
Update: I just looked at Vue.js, and how it allows developers to register Vue.js components and then reference them later in the code. I could potentially load my Vue.js component scripts before my page script. I'm trying to see if I can do something similar in React.
Did I understand you correctly: you have essentially got
a library of custom React components (built by Webpack build #1)
a React app that needs to use some (all) of these components (built by Webpack build #2, totally separate from #1)
?
If yes, then read on.
The "Is this possible in react?" question should instead be "Is this possible in Webpack?", and the answer is "Yes". The following is tested with Webpack 2, but should also work with v.1.
Let's call your projects Lib (your React component library) and App (the library consumer).
In the Lib project:
Create an entry point file, say index.js, that exports all the custom React components like this:
import {Button} from './button';
import {DatePicker} from './DatePicker';
import {TextBox} from './textBox';
export const MyComponentLib = {
Button,
DatePicker,
TextBox
};
Update webpack.config.js to make the project's bundle a UMD library (could also be 'var'), and set the entry point to the above index.js file. Doing so will make your library available via a global variable named MyComponentLib (the name comes from the export above) in the consuming app later on:
...
output: {
path: './dist',
filename: 'mylib.bundle.js',
libraryTarget: 'umd'
},
...
entry: './index.js',
...
On to the App project:
In the index.html file you will have two <script> tags: one for mylib.bundle.js (the output of the Lib project), and another for the bundle of the App project itself. You might have more bundles (app, vendor etc.), I'm just simplifying things here.
Update webpack.config.js to mark the component library as external dependency. Here, MyComponentLib is, again, the name of the global variable the library is available at, and myComponents is the name to use in import statements:
...
externals: {
myComponents: 'MyComponentLib'
},
...
Now, in App you can import a component like this:
import {DatePicker} from 'myComponents';
This will dynamically load DatePicker from the component library at run time via the global variable.
Bonus: if you use eslint, you don't want it to complain about missing modules that you know are external; add this to your .eslintrc:
...
"settings": {
"import/core-modules": ["myComponents"]
},
...

React +(Router) without webpack or browserify

Is it possible to use react with ReactRouter, without using browserify or webpack.
I am following the documentation from http://rackt.github.io/react-router they require react and react-router (require('react-router');). If I use browerifly my generated bundle is about 1MB filesize, which sounds like a lot.
So is it possible to get reactrouter working with including compiled JS from a CDN like https://cdnjs.cloudflare.com/ajax/libs/react-router/0.13.3/ReactRouter.js, instead of bundle all requirements by myself ? If i try to make it work with a CDN, I get an error that Route is not defined. But it looks like it is exported in the cdn file.
I would like to compile my JSX/ES6 react components include the ReactRouter and react JS-files from a cdn and only bundle my components into a new js file.
Is this possible or is browserify and webpack the right way to setup the project ? (I looked at several github repos). I got some doubts because there is no installation guide on http://rackt.github.io/react-router/
like this pseudo html:
<head>
CND :include react, react-router
my code combinded.js
</head>
When you're using the prebuilt version from the CDN, the library is exported onto window.ReactRouter. So, Route is defined on window.ReactRouter.Route.
Since React Router also depends on React, using the CDN/browser build will also require that React is available on window.React.
That said, the CDN version you linked to is, itself, generated with webpack, so I don't expect that you'd gain any file size improvements. You might look into minification/dead code elimination on your browserify bundle to see if it decreases the file size.
One additional info I want to share is the possibility to use externals (https://webpack.github.io/docs/library-and-externals.html) in webpack config.
I use it as following:
externals: {
"react": "React",
"react/addons": "React",
"reflux" : "Reflux"
}
this results in a smaller bundle and you can use react from a CDN as asked in my question. This also decreases the buildtime with gulp.

Resources