简体   繁体   English

如何在 React app.js bundle 中隔离组件

[英]How to isolate components in React app.js bundle

The project index.html load reactjs & babel to render app.js.项目index.html加载 reactjs 和 babel 来渲染 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项目app.js加载 App 和组件 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' ???如何将 Note 组件隔离到它自己的要加载的文件中,类似于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这会抛出错误Uncaught ReferenceError: require is not defined

How this can be done?如何做到这一点?

You need to specify module , but there are some obstacles to be overcome ...您需要指定module ,但有一些障碍需要克服......

You can find some information at:您可以在以下位置找到一些信息:

1. server 1.服务器

It doesn't work directly from the file system, it only works if the file is provided by a server over HTTP(S).它不能直接从文件系统工作,只有在服务器通过 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,一个易于使用的服务器将进入index.html所在的文件夹并运行:

python -m http.server 3000

2. modules 2. 模块

In modern Browsers , you can use import , if you specify type="module" , but that's without JSX:现代浏览器中,如果指定type="module" ,则可以使用import ,但没有 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 eg <button onClick="myFunction()"> , for workarounds see es6-modules-undefined-onclick-function-after-import ) (这也不能“像往常一样”使用例如<button onClick="myFunction()"> ,有关解决方法,请参阅es6-modules-undefined-onclick-function-after-import

3. modules & JSX 3. 模块和 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) :您可以通过指定type="text/babel"data-type="module"来使用 JSX 和模块,但只能向下一级(只有type="text/babel"的文件或内联脚本工作)

// 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 .您可以在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 eg you migrate to using webpack.有一个建议使用eval(Babel.transform( ... ,我不建议使用它,因为如果例如您迁移到使用 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.相反,我建议在本地安装 babel-cli ,并在每次刷新浏览器之前在编译步骤中转换 js 文件。

  1. Install babel-cli:安装 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然后将类型改回type="module" ,将src改回dist/app.js
    (or re-arrange your files as you wish, and adapt the babel --out-dir and import location accordingly) (或根据需要重新排列文件,并相应地调整 babel --out-dir和导入位置)
// 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, eg to the folder /dist :然后转换文件,例如到文件夹/dist
yarn babel ./js/*.js --presets=@babel/preset-react --out-dir dist
  1. Start the server with eg python -m http.server 3000 and open http://localhost:3000 in the browser.使用例如python -m http.server 3000启动服务器并在浏览器中打开http://localhost:3000

  2. When you change some code, transpile again, and just refresh the page in the Browser (F5).当您更改某些代码时,再次转换,然后在浏览器中刷新页面 (F5)。

3. webpack 3. 网络包

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.毕竟,也许您最终会使用webpack或(和) create-react-app ,它们会自动完成所有这些工作,从而带来非常舒适的开发过程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM