React standalone bundle without react library inside - reactjs

I have created standalone bundle which I include in React App. The App itself does not anything know about Extension Bundle (next XB) it load, but the XB does know about App and libraries it use inside. How to make App share library packages it compiled with to XB? I mean if the App compiled with React and React-dom libraries to make XB exclude from compile with such libraries and use them from the App instead?
I put into webpack config to exclude React from compiling:
var config = {
//....
output: {
library: 'videoEditor',
libraryTarget: 'umd',
path: BUILD_PATH+"./../bundles/",
filename: '[name].bundle.js'
},
// ...
}
// .... later just extending config if compiling as standalone
config.externals = Object.assign(config.externals,{'react':'React'});
Yes, that gives me on exit the Bundle without React library (so it size reduces from 190KB to 10KB). But if I try to load it I get an error:
index.js?7afc:1 Uncaught ReferenceError: require is not defined
at eval (index.js?7afc:1)
at Object.<anonymous> (video-editor.bundle.js:80)
at __webpack_require__ (video-editor.bundle.js:30)
at video-editor.bundle.js:73
at video-editor.bundle.js:76
at webpackUniversalModuleDefinition (video-editor.bundle.js:9)
at video-editor.bundle.js:10
Without externals all is working ok.
index.js?7afc:1 is
import React from 'react';
import AppLayout from 'layouts/app';
There inside import React from 'react'; is coming as module.exports = require('react');
I do not understand how to make require work. Seems it is invisible for global space.
update: I have tried to change libraryTarget on any available option: 'umd', 'commonjs', 'this'. The result is the same.
I know about commonChunkPlugin from webpack but I have several separated projects from different sources they compile by different people.

Along with React, you also need to add ReactDOM in your externals from React v0.14.x onwards
externals: {
// Use external version of React
"react": "React",
"react-dom": "ReactDOM"
},

Related

Include only used imports in the packaged bundle ReactJS

I wanna use only one component from Material Ui library . I know i can import only one component using ES6 import but does webpack treeshake and remove other components from the library or include them in production .
Please help me.
Webpack from v2 onwards eliminates unused exports in two steps:
First, all ES6 module files are combined into a single bundle file in which exports that were not imported anywhere are not exported, anymore.
Second, the bundle is minified, while eliminating dead code. Therefore, entities that are neither exported nor used inside their modules do not appear in the minified bundle. Without the first step, dead code elimination would never remove exports.
Unused exports can only be reliably detected at build time if the module system has a static structure.
Webpack doesn't perform tree-shaking by itself. It relies on third party tools like UglifyJS to perform actual dead code elimination.
To do that, you would install it using
npm install --save-dev uglifyjs-webpack-plugin
And then adding it into the config:
webpack.config.js
const path = require('path');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new UglifyJSPlugin()
]
};
So when you add this config, your unused exports are not longer present in the minified build.
Webpack 5 comes with terser-webpack-plugin out of the box, hence you can just import it and configure as you wish.

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"]
},
...

Prevent web pack from bundling react

How do I prevent webpack from bundling react?
Currently I am writing a library that causes a You've loaded two copies of React on the page. error after distribution. I suspect that webpack starts bundling all dependencies, including devDependencies.
Is there any way around that?
In my case it should be possible for the library to get React out of node_modules.
So what I basicly want is, instead of webpack resolving the require('React), it should just leave require('React) untouched.
You can use webpack externals.
externals: {
// Use external version of React
"react": "React"
}
UPD Detailed docs on the resulting code generated for externals.
To make webpack "leave require('React) untouched" you need the following config
{
output: { libraryTarget: 'commonjs' },
externals: { react: true }
...
}
Moelalez, just like Yury Tarabanko stated, externals option allows you import an existing API into applications. For context, say you want to use React from a CDN via a separate tag and still declare it as a dependency via require("react") in your application, you would use externals option to specify that.

Is there a way to load react library files separately and not in the bundled files when using react with babel, webpack and gulp as building tool?

I have an application where I have to build code using babel and react. The application will be built using gulp and webpack for automated build creation and deployment. When using gulp and webpack to convert babel+react code to browser interpretable code, we need to install react using npm and has to be imported in all files, following is the sample code:
import React from 'react';
import ReactDOM from 'react-dom';
import HelloWorld from './helloWorld.jsx';
import HelloMe from './hello-me.jsx';
ReactDOM.render(
<HelloWorld />,
document.getElementById('app-test')
);
ReactDOM.render(
<HelloMe />,
document.getElementById('app-container')
);
Now, the problem is this code when bundled with webpack, bundles react and react-dom library code to the bundled file. So, I would not be able to cache these library files to be loaded in different views. Due to this, the same library code will load again and again in different bundled files. Is there a way to load these files separately and not in the bundled file?
Edit your Wabpack configuration file and specify React & ReactDOM as externals.
externals: {
"react": "React",
"react-dom": "ReactDOM",
},
Then, include React & ReactDOM from CDN or your prefered source.
Whenever you call import React from 'react' or require('react') (or react-dom), Webpack gives you external copy of library

React webpack undefined react in console

I have problem with webpack build I write custom webpack config:
https://github.com/Simproduction/react-client-webpack
but when I run dev or build a project everything work correct but I can't call React from console or use react developers tools
I get error
Uncaught ReferenceError: React is not defined(…)
Could you help me?
My test project,
https://github.com/Simproduction/react-CM
You need to expose React so it is available on the window using the expose-loader:
module: {
loaders: [
{ test: require.resolve("react"), loader: "expose?React" },
]
}
It contains AMD and CommonJS in webpack. You know js loader, right?
If you use AMD ,you know that all js code are in 'define([],function(){ var a=10; ...}) area. if you want print a in console. You should like this
define([],function(){
var a=10;
window.a = a;
})
so, you can edit your main.js. Add this line window.React = React; , but we may use CDN instead of it is common solution.

Resources