I have the following directory structure for my REACTJS app
/ReactJs
-dist
--app
-node_modules
-src
--app
--app/Hello.jsx
----components
----components/PropTest1.jsx
-src/main.html
package.json
webpack.config.js
My Hello.jsx code is:
import React, { Component } from 'react';
import ReactDOM, { render } from 'react-dom';
import PropTest1 from "./components/PropTest1"
var dest = document.querySelector('#container');
class Hello extends Component {
render() {
return (
<div>
<h1>Hello World</h1>
<PropTest1 />
</div>
);
}
}
render(<div><Hello /></div>, dest);
and PropTest1.jsx code is
import React, { Component } from 'react';
class PropTest1 extends Component {
render() {
return (
<div>
<p> My name is no one</p>
</div>
);
}
}
export default PropTest1;
and my webpack.config.js is
var webpack = require('webpack');
var path = require('path')
module.exports = {
mode: "development",
entry: path.resolve(__dirname, 'src') + "/app/Hello.jsx",
output: {
path: path.resolve(__dirname, 'dist') + "/app",
filename: 'bundle.js',
publicPath: '/app/'
},
module: {
rules: [{
test: /\.jsx?/,
include: path.resolve(__dirname,'src'),
loader:'babel-loader'
}]
},
resolve: {
extensions: ['*', '.js', '*.jsx']
}
};
When I am doing
npm run build
I am getting
Module not found: Error: Can't resolve './components/PropTest1'
What looks wrong with the above project, please check.
EDIT: I have added the resolve configuration in my webpack.config.js
The issue here is that you didn't specify the file extension (.jsx) while importing your component (import PropTest1 from "./components/PropTest1")
To solve this, you need to update Webpack config and add a resolve property, which will make Webpack look for files named (in your example) PropTest1.js, PropTest1.jsx until it finds the right one ...
module.exports = {
mode: "development",
entry: path.resolve(__dirname, 'src') + "/app/Hello.jsx",
...,
resolve: {
extensions: ['', '.js', '.jsx']
}
};
Currently,it is looking for components directory within app directory so, you need to use ..
import PropTest1 from "../components/PropTest1"
I found the issue with name of the file. While doing import I had
import Login from "./login";
While name of the file was Login.js
Running on the local machine was not giving error but when I was running on linux, it was giving me a similar error as above.
Related
I want to import the react component that I have bundled using web pack.
I am able to complete the task by copying it locally to that folder and then importing it like
import Any from '.dist/index'
and it is working fine.
But what I want to do is uploading this index.js file to somewhere for example Amazon s3. Now I am not able to import the component in the same way as mentioned above.
My webpack.config.js file, I have used to export my bundled component generated by webpack that I am using in another project by copying the index.js and index.css file is
var path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "index_bundle.js",
libraryTarget: "commonjs2"
},
module: {
rules: [
{ test: /\.(js)$/, use: "babel-loader" },
{ test: /\.css$/, use: ["style-loader", "css-loader"] }
]
},
externals: {
react: "commonjs react"
},
mode: "production",
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
})
]
};
I want to import the component from file url uploaded to s3.
you can do what you are describing with micro apps. A micro app is basically nothing more than a component that is lazy loaded into the host application from a url at runtime. There is no need to install or import the component at design time. There is a library available that lets you do this with a HOC component.
import React from 'react';
import ReactDOM from 'react-dom';
import MicroApp from '#schalltech/honeycomb-react-microapp';
const App = () => {
return (
<MicroApp
config={{
View: {
Name: 'redbox-demo',
Scope: 'beekeeper',
Version: 'latest'
}
}}
/>
);
});
export default App;
You can find more information on how it works here.
https://github.com/Schalltech/honeycomb-marketplace
This is not the way you should package and deploy your React components. AWS S3 is a bucket for storage of files to serve on the web. It's purpose is not to share code files through projects.
You should publish your React components to a registry such as NPM. After you publish your package to the registry, you should be able to install the package into your app as a dependency by doing something like npm install my_package.
I'am trying to use dynamic import with React.lazy. Code is quite simple
import React, { Component, Suspense, lazy, } from 'react';
const BlazyComponent = lazy(() => {
return import('./blazy');
});
class Main extends Component {
render () {
return (<Suspense fallback={<div>Loading...</div>}>
<BlazyComponent/>
</Suspense>);
}
}
export default Main;
So, when I'am starting Webpack devServer, browser console show an error
index.js:114 Uncaught (in promise) Error: Loading chunk 0 failed.
(missing: http://domain/build/0.js)
at HTMLScriptElement.onScriptComplete (index.js:114)
As I can see, index.css and index.js bundles are successfully loaded from http://domain:8080/build/test/index.css and http://domain:8080/build/test/index.js.
But chunk loads from http://domain/build/0.js (webpack devServer ignores port). How can I force chunk load from http://domain:8080/build/0.js.
Webpack config
entry: {
'test/index': [ 'babel-polyfill', './resources/assets/modules/test/index', ],
},
output: {
path: path.resolve(__dirname, './public/build/'),
publicPath: '/build/',
filename: '[name].js',
chunkFilename: '[name].js',
},
...
devServer: {
host: 'domain',
port: 8080,
},
PS. I know, that I can use environment variables, but searching more elegant decision
Try to change your publicPath to http://domain:8080/build/?
See https://webpack.js.org/guides/public-path/#environment-based
I am building an isomorphic react-redux app on top of NodeJS. I am rendering my homePage from the server. However, my styles are not reflected in my rendered view. I would like to import stylesheets just how I do it on the client side. I tried this article and this too, but neither of them actually got me what I want to achieve.
Here are more details on the project.
.babelrc
{
"presets": [ "es2015", "react", "stage-0"],
"plugins": ["transform-decorators-legacy", ["transform-assets", {
"extensions": ["scss"],
"name": "[name].[ext]?[sha512:hash:base64:7]",
}]]
}
webpack.config.js
const path = require('path');
module.exports = [
{
name: 'client',
target: 'web',
entry: './routes/client.jsx',
output: {
path: path.join(__dirname, 'assets'),
filename: 'client.js',
publicPath: '/assets/',
},
resolve: {
extensions: ['.js', '.jsx']
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules\/)/,
use: [{ loader: 'babel-loader'}]
},
{
test: /\.scss$/,
use: [
{ loader: 'isomorphic-style-loader' },
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]',
sourceMap: true
}
},
{ loader: 'sass-loader'}
]
}
],
},
}];
server.js
import express from 'express'
import React from 'react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import MainStore from './views/store/MainStore'
import { StaticRouter } from 'react-router-dom';
import Routes from './routes/routes';
import Template from './views/templates/template';
import { Helmet } from 'react-helmet';
import { renderToString } from 'react-dom/server'
import ReactDOMServer from 'react-dom/server';
import ContextProvider from './routes/contextProvider'
const webpackDevMiddleware = require('webpack-dev-middleware')
const config = require('./webpack/webpack.development.config.js')
const webpack = require('webpack')
const app = express()
const port = 3000
const compiler = webpack(config);
let preloadedState = { shipper: {view: "from_server"} }
app.use('/assets', express.static('./assets'))
app.use(webpackDevMiddleware(compiler, {
publicPath: "/assets/",
}));
app.use(handleRender);
function handleRender(req, res) {
// Create a new Redux store instance
const store = createStore(MainStore, preloadedState)
const css = new Set(); // CSS for all rendered React components
const context = { insertCss: (...styles) => styles.forEach(style =>
css.add(style._getCss())) }
const html = renderToString(
<Provider store={store}>
<StaticRouter context={context}>
<ContextProvider context={context}>
<Routes />
</ContextProvider>
</StaticRouter>
</Provider>
)
const finalState = store.getState()
const helmet = Helmet.renderStatic();
const preloadedState = store.getState()
res.send(renderFullPage(html, preloadedState));
}
function renderFullPage(html, finalState) {
return `
<!doctype html>
<html>
<head>
<title>Redux Universal Example</title>
<style type="text/css">${[...css].join('')}</style>
</head>
<body>
<div id="root">${html}</div>
<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}
</script>
<script src="./assets/client.js"></script>
</body>
</html>
`
}
app.listen(port)
contextProvider.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Routes from './routes.jsx';
export default class ContextProvider extends Component {
static childContextTypes = {
insertCss: PropTypes.func,
}
getChildContext() {
return { ...this.props.context }
}
render() {
const { children, ...props } = this.props
return React.cloneElement(children, props)
}
}
I am importing it in my homePresenter as
import homePageStyle from './home.scss';
and using it in my div in the same component as
<div className="component">
If I change this to
<div className={homePageStyle.component}>
I get an error on the browser
TypeError: style._getCss is not a function at server.js:52:84
On the browser, I could see that the div has class name as 'component'; it;'s just it is not inheriting the styles.
Any suggestions on what I am missing here?
TypeError: style._getCss is not a function at server.js:52:84
Most likely that server-side rendering is not configured properly. If you are not using webpack for compiling server-side bundle, of course, appropriate styles will not loaded, since isomorphic-style-loader had not processed files on server-side.
Check how application is started and ensure, that webpack had been applied for server-bundle and configuration was like this: https://webpack.js.org/configuration/node/
Also you can try ready isomorphic solution with frontend+backend bundling and includes css support, like resolve-app.
I'm trying to convert a working ReactJS application into TypeScript, and I've had some issues getting anything to work properly.
import React from "react";
import * as ReactDOM from "react-dom";
import Application from "./Application";
console.log(React); // undefined
ReactDOM.render(
<Application/>, window.document.getElementById("application-wrapper")
);
The console throws an error at <Application />
When I import react like this, react loads:
import * as React from "react";
However, I want to use the import statement using the default export, because I import React using this import syntax in all the existing components:
import React, {Component} from "react";
export default class Whatever extends Component<Props, State> {
...
}
My tsconfig.json file contains this line allowing synthetic defaults:
"allowSyntheticDefaultImports": true
My webpack.config.js file:
let path = require("path");
let config = {
entry: "./src/main.tsx",
output: {
path: path.resolve(__dirname, "build"),
filename: "bundle.js"
},
devtool: "source-map",
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"]
},
module: {
loaders: [
{
test: /\.tsx?$/,
loader: "ts-loader",
exclude: /node_modules/
}
]
}
};
module.exports = config;
Not sure what I'm missing here....
Set "esModuleInterop": true instead.
In your typescript configuration i.e tsconfig.json "esModuleInterop": true and "allowSyntheticDefaultImports": true. this will allow you to import CommonJS modules in compliance with es6 modules spec.
Module resolution is a little complicated because Typescript does it different than Babel and Webpack. If you want to know more you can check this comment: https://github.com/Microsoft/TypeScript/issues/5565#issuecomment-155216760
Going back to your problem, allowSyntheticDefaultImports tells Typescript to allow default imports from modules with no default export but the emitted code doesn't change. Because of that, you need to move the responsibility of resolving modules to Webpack or Babel.
To achieve that set moduleResolution module to ES6es2015 in the Typescript config file.
The pipeline will look like this:
TS Code => (TypescriptCompiler) => JS Code with ES6 modules => (Webpack modules resolver) => JS Code
I want to create a simple application that outputs "Hello, World!" using isomorphic-webpack.
The most simple way is to use the createIsomorphicWebpack high-level abstraction.
First, you need to have have a basic webpack configuration.
webpack configuration does not need to define any special configuration for isomorphic-webpack, e.g. this will work:
import path from 'path';
import webpack from 'webpack';
const webpackConfiguration = {
context: __dirname,
entry: {
'app': [
path.resolve(__dirname, './app')
]
},
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].js'
},
module: {
loaders: []
}
};
Next, run createIsomorphicWebpack:
import {
createIsomorphicWebpack
} from 'isomorphic-webpack';
createIsomorphicWebpack(webpackConfiguration);
What this does is:
Creates a new webpack compiler.
Runs compiler in watch mode.
Overrides require to use compiled assets.
Therefore, now all you need is to require the entry script:
import {
createServer
} from 'http';
http
.createServer((request, response) => {
response.writeHead(200, {
'Content-Type': 'text/html'
});
response.end(request('./app'));
})
listen(8000);
The entry script must be environment aware, i.e. it must return for node.js process and it must use whatever client specific logic otherwise, e.g.
import React from 'react';
import ReactDOM from 'react-dom';
import style from './style.css';
const app = <div className={style.greetings}>Hello, World!</div>;
if (typeof process === 'undefined' || !process.release || process.release.name !== 'node') {
ReactDOM.render(app, document.getElementById('app'));
}
export default app;
Since this entry script is using css and react, you will need to add the missing loaders to your webpack configuration:
babel-loader and babel-react-preset
css-loader
style-loader