I am developing in a windows environment for the first time (coming from OS).
I have built the basic foundation for a react app, and webpack builds without errors, but only the raw HTML renders. I.e., the ReactDOM process seems to fail or something because my app component doesn't render at all. Note that I leveraged code from an app I built in OS, wondering if that has something to do with it.
See code below. Thank you for having a look.
First my webpack.config.js file:
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');
const SRC_DIR = path.join(__dirname, '/client/src');
const DIST_DIR = path.join(__dirname, '/client/dist');
module.exports = {
entry: `${SRC_DIR}\\index.js`,
output: {
path: path.resolve(__dirname, 'client/dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.jsx?/,
include: SRC_DIR,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015'],
plugins: ['syntax-dynamic-import'],
},
},
{
test: /\.css$/,
loaders: ['style-loader', 'css-loader'],
include: SRC_DIR,
},
],
},
resolve: {
extensions: ['.js', '.jsx']
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development'),
},
}),
new ExtractTextPlugin("styles.css"),
// ,
// new UglifyJSPlugin(),
],
};
Next my html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="shortcut icon" href="https://orig00.deviantart.net/15e4/f/2011/116/f/4/color_wheel_dock_icon_by_andybaumgar-d3ezjgc.png">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<title>SysAdmin Microservices</title>
</head>
<body>
<h1>Node Microservices Server Documentation</h1>
<div id="root"></div>
</body>
</html>
My index.js file with the ReactDOM.render call:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './containers/App.jsx';
ReactDOM.render( <App />, document.getElementById('root'));
Last of all my App.js file:
import React from 'react';
class App extends React {
render() {
console.log('app render has been invoked <-- this never logs to the console ');
return (
<h1>This is the text that does not render in the browser.</h1>
)
}
}
export default App;
You need to have your bundle.js referenced from the index page, else it won't load any of your JS. Will vary based on your folder structure, but something along the lines of this should work:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="dist/bundle.js"></script>
</body>
</html>
Or you could use a Webpack plugin like html-webpack-plugin to inject your bundled JS as a part of your build process.
You can add the script to your bundle manually or use html-webpack-plugin.
This plugin will handle inserting scripts/style to the index html (and more) automatically.
Steps:
Install the plugin: npm install --save-dev html-webpack-plugin
Require it in webpack config: const HtmlWebpackPlugin = require('html-webpack-plugin')
Add the plugin to the plugin config:
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development'),
},
}),
new ExtractTextPlugin("styles.css"),
// ,
// new UglifyJSPlugin(),
]
Related
I am begining with React using Webpack to make the configuration. I made all step by step. No error message on console or browser but the h1 that I want to insert doesn't appear.
I know that React is v.18 but I am using React v.17
App.jsx
import React from 'react'
const App = () => {
return (
<h1>Holaaa</h1>
);
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/app.jsx';
ReactDOM.render (<App/>, document.getElementById ("Hello"))
webpack.config.js
const path = require ("path");
const HtmlWebpackPlugin = require ('html-webpack-plugin')
const MiniCssExtractPlugin = require ('mini-css-extract-plugin')
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve (__dirname, 'dist'),
filename: "bundle.js"
},
mode: "development",
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{test: /\.(js|jsx)$/,
exclude: "/node_modules",
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react']
}
}},
{test: /\html$/,
use: [
{loader: 'html-loader'}
] },
{test: /\.sa[ac]ss$/,
use: ['css-loader',
'style-loader',
'sass-loader']}
]
},
plugins: [
new HtmlWebpackPlugin ({
inject: true,
template: "./public/index.html",
filename: '/menu.html'
}), new MiniCssExtractPlugin ({
filename: "[name].css"
})
]
}
index.html
<title>Document</title>
</head>
<body>
<div id="Hello"> </div>
</body>
</html>
I found the solution. It was the filename config. Was /menu.html. So when localhost was with /menu.html, React render the h1 element.
So, to make render I only have to change /menu.html for index.html in the filename config, refresh and was done!
I am creating a React project using Typescript and I am creating it from scratch without CRA. But I am facing difficulties. I think the error is due to adding typescript and configuring webpack config file for it.
I am unable to find the error here. Please help. I am using typescript.
PFA code
webpack.config.json
Configuration file for webpack
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const isProd = process.env.NODE_ENV === 'production';
const mode = isProd ? 'production' : 'development';
const cssDev = ['style-loader', 'css-loader'];
const cssProd = [MiniCssExtractPlugin.loader, 'css-loader'];
const cssConfig = isProd ? cssProd : cssDev;
const pluginDev = [
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html'
})
];
const pluginProd = [
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html',
minify: {
removeAttributeQuotes: true,
collapseWhitespace: true,
removeComments: true
}
}),
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash].css"
}),
new CleanWebpackPlugin()];
const pluginConfig = isProd ? pluginProd : pluginDev;
const outputDev = {
path: path.resolve(__dirname, 'build'),
filename: 'js/bundle.js',
publicPath: '/'
};
const outputProd = {
path: path.resolve(__dirname, 'build'),
filename: 'js/bundle.[contenthash].js',
publicPath: '/'
};
const outputConfig = isProd ? outputProd : outputDev;
const optimizeProd = {
minimize: true,
minimizer: [
// For webpack#5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
// `...`
new CssMinimizerPlugin(),
],
};
const optimizeConfig = isProd ? optimizeProd : null;
module.exports = {
mode: mode,
entry: './src/index.tsx',
devtool: 'inline-source-map',
output: outputConfig,
plugins: pluginConfig,
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /\.css$/i,
use: cssConfig
},
{
test: /\.html$/i,
use: ['html-loader']
},
{
test: /\.(?:ico|gif|png|jpg|jpeg|svg)$/i,
use: {
loader: "file-loader",
options: {
name: '[sha512:hash:base64:7].[ext]',
outputPath: "images"
}
}
}
]
},
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
},
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin(),
],
},
devServer: {
historyApiFallback: true,
},
}
index.html
Index file which has a div with an id root
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=devide-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" conent="ie=edge" />
<meta name="description" content="Airbnb clone without CRA" />
<title>Scratch React Airbnb App</title>
<link rel="apple-touch-icon" sizes="180x180" href="./assets/ico/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="./assets/ico/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="./assets/ico/favicon-16x16.png">
<link rel="manifest" href="./assets/ico/site.webmanifest">
<link rel="mask-icon" href="./assets/ico/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#00aba9">
<meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="./Fonts.css">
</head>
<body>
<!-- comment -->
<div id="root"></div>
</body>
</html>
App.tsx
App file with typescript
import React , {Suspense, lazy} from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import LoadingScreen from './LoadingScreen';
const Home = lazy(() => import("./Home"));
const Explore = lazy(() => import("./Explore"));
const NotFound = lazy(() => import("./NotFound"));
const App: React.FC = () => {
return (
<main>
<Suspense fallback={<LoadingScreen />}>
<Switch>
<Route path="/" component={Home} exact />
<Route path="/explore" component={Explore} />
<Route component={NotFound} />
</Switch>
</Suspense>
</main>
)
}
export default App
Thanks
How can I use React.js in the front-end of my AdonisJs project?
I've tried to install react with npm install react I thought this will works correctly. I made a file app.js with this code:
var React = require('react');
var ReactDOM = require('react-dom');
export default class Index extends Component {
render() {
return (< h1 > hello world! < /h1>)
}
}
ReactDOM.render( < Index / > , document.getElementById('example'))
But this isn't working at all, I don't know what to do more I have searched about how to use React in Adonis but I didn't find anything interesting.
I strongly suggest you to use WebPack for this task.
create a webpack.config.js file in your root directory:
maybe your code need some changes but this is the idea:
const webpack = require('webpack');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var path = require('path');
var pkgBower = require('./package.json');
module.exports = {
target: "web",
devtool: "source-map",
node: {
fs: "empty"
},
entry: {
'app': path.join(__dirname, 'react-app', 'Index.jsx')
},
resolve: {
modules: [__dirname, 'node_modules', 'bower_components'],
extensions: ['*','.js','.jsx', '.es6.js']
},
output: {
path: path.join(__dirname, 'public', 'src'),
filename: '[name].js'
},
resolveLoader: {
moduleExtensions: ["-loader"]
},
module: {
loaders: [
{
test: /jquery\.flot\.resize\.js$/,
loader: 'imports?this=>window'
},
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react', 'stage-0'],
compact: false
}
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test: /\.woff|\.woff2|\.svg|.eot|\.ttf/,
loader: 'url?prefix=font/&limit=10000'
},
{
test: /\.(png|jpg|gif)$/,
loader: 'url?limit=10000'
},
{
test: /\.scss$/,
loader: 'style!css!sass?outputStyle=expanded'
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
}),
new CopyWebpackPlugin([{
from: 'img',
to: 'img',
context: path.join(__dirname, 'react-app')
}, {
from: 'server',
to: 'server',
context: path.join(__dirname, 'react-app')
}, {
from: 'fonts',
to: 'fonts',
context: path.join(__dirname, 'react-app')
}]),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false },
mangle: true,
sourcemap: false,
beautify: false,
dead_code: true
}),
new webpack.ContextReplacementPlugin(/\.\/locale$/, 'empty-module', false, /js$/)
]
};
Then put your app in your root directory, in a folder react-app/ and your components can go inside that folder:
For example your file: [Index.jsx]
import React from 'react';
import ReactDOM from 'react-dom';
class Index extends Component {
render() {
return (< h1 > hello world! < /h1>)
}
}
ReactDOM.render( < Index / > , document.getElementById('example'));
you don't need to export this Index component in this case, but in case you need to just use export default ComponentName at the end of your component file.
The next step is in your routes file (I'm using AdonisJS 4) but is very similar for the version 3.x
Route.any("*", ({ view, response }) => (
view.render('index')
))
Then your index (.njk, or .edge) file (under resources/views) should look something like this:
<html>
<head>
<link rel="stylesheet" href="/src/styles.css">
<script type="text/javascript" src="/src/app.js"></script>
</head>
<body>
<div id="example"></div>
</body>
</html>
--
You need to install some npm/ packages with npm or yarn,
and remember to run in another terminal window or tab,
webpack -d --watch --progress
Regards.
This works. You are missing React.Component.
var React = require('react');
var ReactDOM = require('react-dom');
export default class Index extends React.Component {
render() {
return (< h1 > hello world! < /h1>)
}
}
ReactDOM.render( < Index / > , document.getElementById('example'))
Alternatively you can use import React, {Component} from 'react'; if you want to use your code structure.
For decoupled use, just build your React app and copy the build to Adonis public folder.
I am not seeing any output on the screen, but I am also not getting any errors. I will post what I can think of being needed. I am starting a new project and trying things a little differently so some help is needed.
Update: Here is how I launch the app. I run npm run server in the console from root directory and this is the script "server": "nodemon --watch server --exec babel-node -- server/index.js"
webpack.config:
import path from 'path';
import webpack from 'webpack';
export default {
devtool: 'eval-source-map',
entry: [
'webpack-hot-middleware/client',
path.join(__dirname, './client/index.js')
],
output: {
filename: 'bundle.js',
path: '/',
publicPath: '/'
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.HotModuleReplacementPlugin()
],
module: {
loaders: [
{
test: /\.js$/,
include: path.join(__dirname, 'client'),
loaders: [ 'react-hot-loader', 'babel-loader' ]
}
]
},
resolve: {
extensions: ['*', '.js']
}
}
index.js:
import React from 'react';
import { render } from 'react-dom';
import App from './components/App';
render(<App />, document.getElementById('app'));
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta content="width=device-width, initial-scale=1" name="viewport" />
</head>
<body>
<div id="app"></div>
<scrip src="bundle.js" type="text/javascript"></scrip>
</body>
</html>
App:
import React from 'react';
class App extends React.Component {
render() {
return (
<h1>!Hello from react!</h1>
)
}
}
export default App;
Server index.js:
import express from 'express';
import path from 'path';
import webpack from 'webpack';
import webpackMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import webpackConfig from '../webpack.config.dev';
const app = express();
const compiler = webpack(webpackConfig);
app.use(webpackMiddleware(compiler));
app.use(webpackHotMiddleware(compiler, {
hot: true,
publicPath: webpackConfig.output.publicPath,
noInfo: true
}));
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, './index.html'));
});
app.listen(3000, () => {
console.log('listening on port 3000');
});
Typo in <scrip src="bundle.js" type="text/javascript"></scrip>
<script> instead <scrip>
Can anyone suggest why this error might be coming up? thanks!
The electron (Chromium) developer console gives this error: "Uncaught SyntaxError: Unexpected reserved word" and refers to appentrypoint.js
clicking on appentrypoint.js in the console shows that it looks like this:
(function (exports, require, module, __filename, __dirname, process, global) { import React from 'react';
window.React = React;
export default function appEntryPoint(mountNode) {
React.render(<img src='http://tinyurl.com/lkevsb9' />, mountNode);
}
});
the actual source file for appentrypoint.js looks like this:
import React from 'react';
window.React = React;
export default function appEntryPoint(mountNode) {
React.render(<img src='http://tinyurl.com/lkevsb9' />, mountNode);
}
The HTML file looks like this:
<!DOCTYPE html>
<html>
<body >
<div id="root" class='section'>
</div>
<script src="http://localhost:3000/dist/bundle.js"></script>
<script type="text/javascript">
(function () {
var mountNode = document.getElementById('root');
var appEntryPoint = require('./appentrypoint.js');
appEntryPoint(mountNode);
})();
</script>
</body>
</html>
webpack.config.base looks like this:
var path = require('path');
module.exports = {
module: {
loaders: [{
test: /\.jsx?$/,
loaders: ['babel-loader'],
exclude: /node_modules/
}]
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
libraryTarget: 'commonjs2'
},
resolve: {
extensions: ['', '.js', '.jsx'],
packageMains: ['webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main']
},
plugins: [
],
externals: [
// put your node 3rd party libraries which can't be built with webpack here (mysql, mongodb, and so on..)
]
};
and webpack.config.development looks like this:
/* eslint strict: 0 */
'use strict';
var webpack = require('webpack');
var webpackTargetElectronRenderer = require('webpack-target-electron-renderer');
var baseConfig = require('./webpack.config.base');
var config = Object.create(baseConfig);
config.debug = true;
config.devtool = 'cheap-module-eval-source-map';
config.entry = [
'webpack-hot-middleware/client?path=http://localhost:3000/__webpack_hmr',
'./app/appentrypoint'
];
config.output.publicPath = 'http://localhost:3000/dist/';
config.module.loaders.push({
test: /^((?!\.module).)*\.css$/,
loaders: [
'style-loader',
'css-loader'
]
}, {
test: /\.module\.css$/,
loaders: [
'style-loader',
'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!'
]
});
config.plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({ "global.GENTLY": false }),
new webpack.DefinePlugin({
'__DEV__': true,
'process.env': {
'NODE_ENV': JSON.stringify('development')
}
})
);
config.target = webpackTargetElectronRenderer(config);
module.exports = config;
Browsers don't natively have module systems, so your <script> tag containing require('./appentrypoint.js') will not run without being included in the bundle.
Assuming the rest of your webpack configuration is correct, (at a quick glance, it looks good) you can resolve this issue by first removing that second <script> block from your HTML file. Your HTML file should then look like:
<!DOCTYPE html>
<html>
<body >
<div id="root" class='section'></div>
<script src="http://localhost:3000/dist/bundle.js"></script>
</body>
</html>
Now you need to fix appentrypoint.js, like so:
import React from 'react';
// if using ES6, best practice would be to switch "var" with "const" here
var mountNode = document.getElementById('root');
React.render(<img src='http://tinyurl.com/lkevsb9' />, mountNode);
The main change here is that you're defining your mount node in the root of your app, and then immediately telling React.render() to render your component on that node. Also, you should have no need for window.React = React;.
This should work, but if you're running the latest version of React you may see something like "Warning: React.render is deprecated." This is because the Facebook devs decided to separate out DOM-related tools from React into a completely separate library, React-DOM. So, for future reference, you would npm install react-dom --save and your root would actually look like this:
import React from 'react';
import ReactDOM from 'react-dom';
const mountNode = document.getElementById('root');
ReactDOM.render(<img src='http://tinyurl.com/lkevsb9' />, mountNode);
In React 0.15.0 and beyond, React.render() will not be a function, so best to get in the habit of using their new API sooner than later.