2

The project index.html load reactjs & babel to render app.js.

<body>
    <h1>Placeholder title</h1>
    <div id="root"></div>
    
    <script src='js/react.production.min.js'></script>
    <script src='js/react-dom.production.min.js'></script>
    <script src='js/babel.min.js'></script>
    <script type='text/babel' src='js/APP/app.js'></script>
</body>

The project app.js load the App and the component Note

function App() {
    return <Note note='Hello World!' />;
}

function Note({ note }){
    return <div>{ `Note: ${note}` }</div>;
}

ReactDOM.render(<App />, document.getElementById('root'));

How to isolate Note component into it own file to be loaded similar to import Note from './components/Note'???

import Note from './components/Note'
function App() {
    return <Note note='Hello World!' />;
}

In this case

const Hello = require('./components/Hello') // option 1 error
import Hello from './components/Note' // option 2 error

function App() {
    return <Note note='Hello World!' />;
}

This throw the error Uncaught ReferenceError: require is not defined

How this can be done?

Zyncho
  • 407
  • 6
  • 12
  • It sounds like you are talking about creating some sort of component library. Tools like create-react-app will absolutely not expose individual components because it's goal is to create a deployable app. You can look at any of your favorite libraries and see how they are building their deployments using webpack, rollup, or any other bundler. Try looking at those libraries, see how they configured their build, make an attempt to implement that and update your question with what you have tried. – Alexander Staroselsky Oct 21 '21 at 18:51

1 Answers1

0

You need to specify module, but there are some obstacles to be overcome ...

You can find some information at:

1. server

It doesn't work directly from the file system, it only works if the file is provided by a server over HTTP(S).

There are many possible solutions. If you have python installed, an easy to use server would be to go into the folder where the index.html is and run:

python -m http.server 3000

2. modules

In modern Browsers, you can use import, if you specify type="module", but that's without JSX:

// index.html
<!DOCTYPE html><html lang="en"><head>
    <script type="module">
        import { doSomething } from './js/module.js';
        doSomething();
    </script>
</head></html>

// js/module.js
import { doSomethingElse } from './module2.js';

export const doSomething = function(){
    console.log('done something.');
    doSomethingElse();
};

// js/module2.js
export const doSomethingElse = function(){
    console.log('done something else.');
};

(This also doesn't work "as usual" with e.g. <button onClick="myFunction()">, for workarounds see es6-modules-undefined-onclick-function-after-import)

3. modules & JSX

You can use JSX and a module by specifying type="text/babel" and data-type="module", but only one level down (only the files or inline scripts with type="text/babel" work):

// index.html
<!DOCTYPE html><html lang="en"><body>
    <h1>Placeholder title</h1>
    <div id="root"></div>
    <script src='js/react.production.min.js'></script>
    <script src='js/react-dom.production.min.js'></script>
    <script src='js/babel.min.js'></script>
    <script type="text/babel" data-type="module" src='js/app.js'></script>
</body></html>

// js/app.js
import { Note } from './js/note.js';

function App() {
    return <Note note='Hello World!' />; // <-- works
}

ReactDOM.render(<App />, document.getElementById('root')); // <-- works

// js/note.js
export function Note({ note }){
    return React.createElement( 'div', null, `Note: ${note}`); // <-- works
    //return <div>{ `*Note: ${note}` }</div>;   // <-- doesn't work
}

You can read more information (and maybe workarounds) in how-to-make-script-type-both-text-babel-and-module. There is a suggestion to use eval(Babel.transform( ..., which I would not recommend to use, because you will not be able to re-use the code if e.g. you migrate to using webpack.

Instead I would recommend to install the babel-cli locally, and convert the js files in a compile step every time before refreshing the browser.

  1. Install babel-cli:
yarn add @babel/cli @babel/core @babel/preset-react --dev
  1. Then change the type back to type="module", and the src to dist/app.js
    (or re-arrange your files as you wish, and adapt the babel --out-dir and import location accordingly)
// index.html
<!DOCTYPE html><html lang="en"><body>
    <h1>Placeholder title</h1>
    <div id="root"></div>
    <script src="js/react.production.min.js"></script>
    <script src="js/react-dom.production.min.js"></script>
    <script src="js/babel.min.js"></script>
    <script type="module" src="dist/app.js"></script>
</body></html>

// app.js
import { Note } from './note.js'; // <-- relative to `/dist` now

function App() {
    return <Note note='Hello World!' />; // <-- will work in transpiled /dist folder
}

ReactDOM.render(<App />, document.getElementById('root')); // <-- will work in transpiled /dist folder

// note.js
export function Note({ note }){
    // return React.createElement( 'div', null, `Note: ${note}`); // <-- works
    return <div>{ `*Note: ${note}` }</div>;   // <-- will work in transpiled /dist folder
}
  1. Then transpile the files, e.g. to the folder /dist:
yarn babel ./js/*.js --presets=@babel/preset-react --out-dir dist
  1. Start the server with e.g. python -m http.server 3000 and open http://localhost:3000 in the browser.

  2. When you change some code, transpile again, and just refresh the page in the Browser (F5).

3. webpack

After all, maybe you will endup using webpack or (and) create-react-app, which does all this automatically, leading to a very comfortable development process.

kca
  • 4,856
  • 1
  • 20
  • 41