Importing React Component from bundled file - reactjs

I have a bunch of React components in a folder and I can import each one individually like this:
import Component1 from '../components/component1/component1';
import Component2 from '../components/component2/component2';
Using the components like this works fine. However, when I bundle all the components using Webpack, the following code returns an empty object when I try to import the component.
import Component1 from '../dist/bundle.js';
I can't render this component. How do I export the components when bundling files?

Simply put you cannot import any modules from a bundle.
You need to include this code inside the source and then bundle it together

Actually you can do that. In my situation I needed react components in backbone application so what I did:
In react exposed components that should be importable by exporting them in entry point (usually index.js) like:
import React from 'react';
import ReactDOM from 'react-dom';
import Header from './components/Header/Header';
export {
React,
ReactDOM,
Header
};
Made my bundle output as library:
output: {
path: /some/path/of/your/lib,
library: 'reactapp',
libraryTarget: 'umd',
filename: `app${jsExtension}`,
},
Then bind name to file path in requirejs config:
reactapp: '/some/path/of/your/lib/app.js'
Then in code I can import that bundle as reactapp like:
define(["reactapp"], function(reactapp) {
// reactapp is object containing React, ReactDOM, Header
});

Related

When saying import React from 'react'; where is React imported from?

There seems to be no corresponding folder or file named 'react'. Maybe using npm start gives the JSX file access to 'react', I don't know where 'react' is located though.
Basically, where is 'react' located?
I looked in the node_modules folder, and there is a subfolder named react. However, there is no file named React in there.
import React from 'react';
In the above line of code, I can not figure out where React is. I tried looking in the 'react' folder that is a subfolder of node_modules
React is exported from the React package.
import React from 'react';
In the above line, you are importing a default export. You can give it any name you want instead of React.
In the React source code you can find this default export defined in package.json.
The word React is where you assigned whatever the 'react' library exported as default.
if you open the node_modules/react/package.json file and check it you can find following line of code,
...
"main": "index.js",
"exports": {
".": {
"react-server": "./react.shared-subset.js",
"default": "./index.js" // <----------------------------- see here
},
"./package.json": "./package.json",
"./jsx-runtime": "./jsx-runtime.js",
"./jsx-dev-runtime": "./jsx-dev-runtime.js"
},
The package.json says the entry point is index.js so if you check the content of index.js, (exports["."]["default"] says use index.js for default import ( ie import DefaultReact from 'react' ))
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react.production.min.js');
} else {
module.exports = require('./cjs/react.development.js');
}
This is not just a react specific thing, you can learn how to create custom packages from here.

what does babel-plugin-named-asset-import do

Ok I've looked everywhere and there is no documentation on this Babel module
--babel-plugin-named-asset-import
can someone please explain what it is for and how it works.
Looks like its purpose is to import named exports from non JS/CSS assets. Currently, within the CRA, it appears to only be implemented for svg assets. The goal is to offer another way to import SVGs as React components versus the standard import as a url that needs to be applied to an img element.
Without plugin (default import)
import * as React from 'react';
import logo from './logo.png'; // import file as a url
function Header() {
return <img src={logo} alt="logo" />;
}
export default Header;
With plugin (named import)
import * as React from 'react';
import { ReactComponent as Logo } from './logo.svg'; // import file as a React component
function Header() {
return <Logo />;
}
export default Header;
Update
Going deeper, it appears that the plugin aids in importing svg files in the following ways:
import logo from "logo.svg"; // default import
import { logoUrl } from "logo.svg"; // named import
import { ReactComponent as Logo } from "#svgr/webpack?-svgo!logo.svg"; // ReactComponent import
The CRA specifically targets svg file formats as shown in their test suites. As to whether or not it supports other non-js files, not likely (especially since the babel plugin is only utilized once in the CRA webpack config).
As mentioned in the svgr docs:
SVGR can be used as a webpack loader, this way you can import your SVG directly as a React Component.
This particular plugin aims to import any svg file as the default export.
Please note that by default, #svgr/webpack will try to export the React Component via default export if there is no other loader handling svg files with default export.
Whereas the CRA appears to utilize file/url loader for the default/named exports and specifically maps a ReactComponent named export to the svgr webpack plugin.

how to import component in index.js in react.js

I have created component folder in src folder and tried to write simple greeting program for that I have created 3 files:
GreetUser.jsx
index.jsx
index.html
while compiling it is showing that could not find required index.js file.
I have written 3 files in Component folder and have imported GreetingUser module in the index.jsx file and while compiling it is showing that could not find required index.js file.
1.GreetingUser.jsx
import React , {component} from 'react';
class GreetUser extends component
{
render()
{
return <h1>Greetings from suraj!!!!</h1>;
}
}
export default GreetUser;
2.index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import * as serviceWorker from './serviceWorker';
import GreetUser from './Component/GreetUser.jsx';
ReactDOM.render(<GreetUser/>,document.getElementById('aaa'));
serviceWorker.unregister();
Could not find a required file.
Name: index.js
Fundamentally, JSX just provides syntactic sugar for the React.createElement(component, props, ...children) function.
index file must with .js extension and not jsx is not react component.
index.js file in a folder lets you perform an import from the folder implicitly without specifying the index.js in the import statement – just like how web servers will serve up the index.html in a folder without you needing to explicitly put the index.html in the URL.
You can modify webpack configuration if you need it.
You can look at additional answers: Renaming index.js to index.jsx in react app and Why does create-react-app creates both App.js and index.js?

Does the use of es6 named imports reduce the bundle size when using webpack

I need to understand when I use a named import like this
import { render } from 'react-dom'
does webpack include in the bundle only the render method or the whole module especially when using tree shaking by setting module to false in babel configuration and let webpack take care about them?
Also in the case of importing react
import React from 'react'
&&
import React, { Component, PropTypes } from 'react'
what's the right way?
Tree-Shaking is applicable for modules which can be statically analysed (to get the entire dependency tree without running the code) -
and it is ONLY for ES2015 Modules and NOT CommonJS(node) modules.
react, react-dom, as of this writing (react#15.4.x), are NOT published as ES2015 modules. So either of these -
import { render } from "react-dom";
or
import ReactDOM from "react-dom";
will result in the entire react-dom being included in your bundle. The same applies for react and other libraries which are published as CommonJS modules or UMD.

import App from './App';

I am trying react based on create-react-app. I'm new to react.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById('root')
);
./App in import App from './App'; is not clear to me when and where is this created, is this done by babel?
file strucutre
my-app/
README.md
node_modules/
package.json
.gitignore
public/
favicon.ico
index.html
src/
App.css
App.js
App.test.js
index.css
index.js
logo.svg
App.js
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>myComponent</div>
)
}
}
export default App;
tl;dr
No, it is not done by Babel, instead it is done by create-react-app package.
All the files and folders in that folder are created automatically when you run,
create-react-app your-new-app-name
import App from './App'
The above line is used for importing the class you have written in the file App.js under the same directory.
Next, the difference between,
import App from './App'
and
import App from 'App'
Use the first if you want to import any user defined files and second for importing packages. As Shubham Khatri mentioned, for importing files, it is technically same if you did or did not use .js extension.
The longer version
create-react-app is a starter kit for people who are new to React or for who are lazy enough to build an app from scratch. What create-react-app does is, it will give you a minimal running React app with a solid folder structure. As given in their documentation, you can install that globally by giving,
npm install -g create-react-app
After this whenever you want to create a new app, what you want to do is,
create-react-app your-new-app-name
This will automatically generate a folder with all the files you mentioned.
Within the folder when you open the file public/index.html, you can see a line
<div id="root"> </div>
And on the src/index.js, you can find,
ReactDOM.render(
<App />,{}
document.getElementById('root')
);
If you are familiar with javascript, you may know that document.getElementById('root') is used to match any tag in HTML with ID as root. So the above snippet means that, they are rendering the <App> component of react to div with ID root. This is how React communicates with HTML page.
Rather that writing all the component codes in a single file, it is a good standard to write each components in different files. Here, App.js is a component that basically renders the text myComponent. For using this component in other files, you have to do two things.
Export the component from the file where it is defined. (export default App;)
Import the component to the file where it is used. (import App from './App')
General syntax for import is,
import className, { functionName } from 'packageName'
or
import className, { functionName } from './path-to-file/fileName'
Note: It is that ./ which tells the compiler whether to look on to node_modules folder or the path you mentioned. Use that strictly when you need to import user defined files.
Hope this helps!
When you import your Component like
import App from './App';
It will import your file App.js that is present in the same direcotry as index.js
In webpack configuration we specify which types of files babel needs to build and there if we specify .js or .jsx, it takes by default the extension of the file when we import it. we do not explicitly mention it. You can change your immport to be like
import App from './App.js';
which is technically the same.
The create-react-app npm package makes use of webpack to build your code which you can see from the package/react-scripts/package.json in the github directory

Resources