I am struggling to find an example of how to set the public path of an output file of a webpack bundle.
The documentation says:
If you don't know the publicPath while compiling, you can omit it and
set __webpack_public_path__ on your entry point.
Like so:
__webpack_public_path__ = myRuntimePublicPath
Would anyone be kind enough to create a JSFiddle example how this can be done?
Nothing has changed after almost two years. It's still surprisingly difficult to find an example of setting public path for webpack at runtime.
Prerequisites
webpack 4.5.0
an app big enough to leverage code splitting
For simplicity let's say our html lives in index.html and app entry point is app.js
An example that works
index.html
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<div id="app"></div>
<script type="application/javascript">
window.resourceBasePath = '/path/to/scripts/on/server/';
</script>
<script type="application/javascript" src="/path/to/scripts/on/server/app.js"></script>
</body>
</html>
app.js
// it is important to set global var before any imports
__webpack_public_path__ = window.resourceBasePath;
import React from 'react';
import ReactDOM from 'react-dom';
import {store, history} from './store';
const render = () => {
import('./root').then((module) => {
const Root = module.default;
ReactDOM.render(
<Root
store={store}
history={history}
/>,
document.getElementById('app'),
);
});
};
render();
if (module.hot) {
module.hot.accept('./root', render);
}
An example that doesn't work
Webpack publicPath documentation says it's enough just to set a global variable with the right name. I did that:
index.html
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<div id="app"></div>
<script type="application/javascript">
__webpack_public_path__ = '/path/to/scripts/on/server/';
</script>
<script type="application/javascript" src="/path/to/scripts/on/server/app.js"></script>
</body>
</html>
app.js
import React from 'react';
import ReactDOM from 'react-dom';
import {store, history} from './store';
const render = () => {
import('./root').then((module) => {
const Root = module.default;
ReactDOM.render(
<Root
store={store}
history={history}
/>,
document.getElementById('app'),
);
});
};
render();
if (module.hot) {
module.hot.accept('./root', render);
}
In this case my app fails complaining in console it couldn't load 0.js from current path to index.html. Which means that setting public path didn't have any impact.
Related
I wanted divide my project into two bundles. Here's my simplified App.js
import React, { Suspense, useState, useEffect, useRef } from 'react';
import loadGif from './images/731.gif';
const HospitalDashboard = React.lazy(() => import('./HospitalDashboard'));
const OperatorDashboard = React.lazy(() => import('./OperatorDashboard'));
function App () {
const [credentials, setCredentials] = useState(null);
return (
<Suspense fallback={<img className='load' src={loadGif}/>}>
{credentials.role == 'operator' ?
<OperatorDashboard/> :
<HospitalDashboard/>}
</Suspense>
);
}
export default App;
and here's my simplified index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js?version=256"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
<title>Dashboard</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
Both in OperatorDashboard and HospitalDashboard I am using daterangepicker followingly:
import $ from 'jquery';
...
useEffect(()=>{
$('#datePicker').daterangepicker(initOptions,onCallback)
},[])
In HospitalDashboard everything works fine but in OperatorDashboard I am getting this error:
jquery__WEBPACK_IMPORTED_MODULE_1___default(...)(...).daterangepicker is not a function
It is somehow related to React.lazy and bundles but I don't know how to solve it. If I use ordinary import without React.lazy, everything works fine again. Thanks for help!
I've just started using react and was using the create-react-app from npm until today. I've gotten the react and reactdom code from
https://unpkg.com/react#15/dist/react.js
https://unpkg.com/react-dom#15/dist/react-dom.js
I've saved the files as:
/Test/react/react.js
/Test/react/react-dom.js
This is my index.js:
<!--/Test/index.js-->
<html>
<head>
<title>React Hello World</title>
</head>
<body>
<div id="root"></div>
<script src="react/react.js"></script>
<script src="react/react-dom.js"></script>
<script src="App.js"></script>
</body>
</html>
I have created a module called Greetings, given below:
//Test/Components/Greetings.js
class Greetings extends React.Component {
render() {
return React.createElement(
"h1",
null,
"Greetings, " + this.props.name + "!"
);
}
}
export default Greetings;
And I've created an App.js, given here:
//Test/App.js
import Greetings from "./Components/Greetings";
ReactDOM.render(
React.createElement(Greetings, { name: "Me" }),
document.getElementById("root")
);
I'm getting this error:
Uncaught SyntaxError: Unexpected identifier
Is there an easy way to import a react module?
import and export are Node.js keywords. On the client-side you don't need them. Simply include your javascript files in the html:
<script src="App.js"></script>
<script src="Greetings.js"></script>
I'm new to React. I have a local development server (node http-server) and have installed material-ui package.
According to the material-ui docs, to add a component, I simply import it like any other module:
import Button from '#material-ui/core/Button';
However, when I try this, my webserver is returning a 404 and Firefox console outputs this: Loading module from “http://localhost:8080/node_modules/#material-ui/core/Button/” was blocked because of a disallowed MIME type (“text/html”)
The directory is accessible because I can reference the ./node_modules/#material-ui/core/Button/Button.js file and it is returned by http-server. But if I import that file, I get
SyntaxError: import not found: default.
I've tried importing index.js from that directory, but get same error.
How do I import the Button component (as shown in the material-ui example) correctly?
Here is my code (being served by http-server on localhost:8080)
(I am using npx babel to compile the JSX to js before serving)
test.html:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Test React</title>
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
</head>
<body>
<div id="app"></div>
<!-- React scripts -->
<script type="module" src="./test.js"></script>
</body>
</html>
test.js:
import { Mod1 } from './module1.js';
export class TestComponent extends React.Component
{
render()
{
return <h1>Hello world!</h1>;
}
}
export const TestC2 = () =>
{
return <h2>This is a h2</h2>;
}
ReactDOM.render(<div><TestComponent /><TestC2 /><Mod1 /></div>, document.getElementById('app'));
module1.js
// module1
import Button from './node_modules/#material-ui/core/Button';
export class Mod1 extends React.Component
{
constructor(props)
{
super(props);
this.state = {};
}
componentWillMount(props)
{
console.log("willMount", props);
}
componentDidMount(pp, ps)
{
console.log("didMount", pp, ps);
}
render()
{
console.log('render', this.props, this.state);
return <Button />;
}
}
I'm trying to render react isomorphicaly, and it renders but I get the Warning/Error in client saying:
I'm using jspm and npm as package managers;
warning.js:25 Warning: render(...): Replacing React-rendered children with a new root component. If you intended to update the children of this node, you should instead have the existing children update their state and render the new components instead of calling ReactDOM.render.
The source outputed by server renderToString:
<div id="reactRoot"><div data-reactroot="" data-reactid="1" data-react-checksum="845161664"><marquee data-reactid="2"><h1 data-reactid="3">App</h1></marquee></div></div>
The source replaced by react after render:
<div id="reactRoot"><div data-reactid=".0"><marquee data-reactid=".0.0"><h1 data-reactid=".0.0.0">App</h1></marquee></div></div>
The express server middleware:
import App from './components/App/App.jsx';
// [...] Express code removed for brevity
app.use('*', (req, res, next) => {
try {
res.render('index.html', {
reactHtml: renderToString(
<App />
)
});
} catch (err) {
next(err);
}
});
The index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>App</title>
<script>
console.log('Running on <%- #env %> environment!');
<% if (#env == 'development') : %>
System.import('systemjs-hot-reloader/default-listener.js');
<% end %>
System.import('/app.jsx!')
.catch(console.error.bind(console));
</script>
</head>
<body>
<div id="reactRoot"><%- reactHtml %></div>
</body>
</html>
I'm using ect as templating engine here;
The app.jsx:
import { render } from 'react-dom';
import App from './components/App/App.jsx';
const mountPoint = document.getElementById('reactRoot');
render(
<App />,
mountPoint
);
The App/App.jsx:
import React from 'react';
const App = () => (
<div>
<marquee><h1>App</h1></marquee>
</div>
);
export default App;
Use renderToStaticMarkup
// render the dynamic code of the page to a string.
var appHtml = React.renderToString(<Application/>);
// now use React as a static templating language to create the <html>,
// <head>, and <body> tags
var fullPageHtml = React.renderToStaticMarkup(<HtmlPage content={appHtml}/>);
res.write(fullPageHtml);
Full Issue resolution discussion can be found here.
https://github.com/aickin/react-dom-stream/issues/4
I am using webpack + react as my application. Below is my index.jsx file.
import $ from 'jquery'
import React from 'react';
import ReactDOM from 'react-dom';
import load from 'little-loader';
import './main.css';
import './component';
import Search from './search/search'
load('http://api.map.baidu.com/api?v=2.0&ak=gNO2wKVBNupZfafi0bl0sW3dIKqAHn4l', function(err){
console.log('err:', err);
});
// load('baidu.js');
// document.body.appendChild(component());
ReactDOM.render(<Search />, document.getElementById('search'));
var map = new BMap.Map("container");
It imports a third party javascript from this link: http://api.map.baidu.com/api?v=2.0&ak=gNO2wKVBNupZfafi0bl0sW3dIKqAHn4l.
If you open this link, the content is defined as follows:
(function(){
window.BMap_loadScriptTime =
(new Date).getTime();
document.write('<script type="text/javascript" src="http://api.map.baidu.com/getscript?v=2.0&ak=gNO2wKVBNupZfafi0bl0sW3dIKqAHn4l&services=&t=20160401164342"></script>');
})();
Now I want to use the api from this library by
var map = new BMap.Map("container");
But I got an error complaining BMap is not defined. I guess I didn't import this library correctly, how should I import it?
My index.html looks like below:
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id='search'>
</div>
<script type="text/javascript" src="bundle.js" charset="utf-8"></script>
</body>
</html>