json-loader in webpack.config.js not working - javascript

I'm trying to follow a react tutorial, My webpack.config.js file is as follows:
var webpack = require("webpack");
var pth = require("path");
module.exports = {
entry: "./src/index.js",
output: {
path: __dirname + "/dist",
filename: "bundle.js"
},
devServer: {
inline: true,
contentBase: './dist',
port: 3000
},
module: {
rules: [
{ test: /\.js$/, exclude: /(node_modules)/, use: 'babel-loader' },
{ test: /\.json$/, exclude: /(node_modules)/, use: 'json-loader' }
]
}
}
While my Code files are as follows: I have made components here in lib.js and rendering is being done in index.js which ultimately is called in a HTML div in index.html
lib.js
import React from 'react'
import text from './titles.json'
export const hello = (
<h1 id='title'
className='header'
style={{backgroundColor: 'purple', color: 'yellow'}}>
{text.hello}
</h1>
)
export const goodbye = (
<h1 id='title'
className='header'
style={{backgroundColor: 'white', color: 'red'}}>
{text.goodbye}
</h1>
)
index.js
import React from 'react'
import {render} from 'react-dom'
import {hello, goodbye} from './lib'
const design = {
backgroundColor: 'red',
color: 'white',
fontFamily:'verdana'
}
render(
<div>
{hello}
{goodbye}
</div>,
document.getElementById('react-container')
)
When I run webpack -w command, I experience the following error
ERROR in ./src/titles.json
Module parse failed: Unexpected token m in JSON at position 0
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token m in JSON at position 0
at Object.parse (native)
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:447:3)
# ./src/lib.js 12:14-38
# ./src/index.js
ERROR in chunk main [entry]
bundle.js
Cannot read property 'replace' of undefined
My JSON file is as follows:
titles.json
{
"hello": "Bonjour!",
"goodbye": "Au Revoir"
}
My Module verions are as follows:
webpack 4.1.1
json-loader 0.5.7
I have installed webpack and json-loader globally using npm install
TIA

I notice you are using webpack 4. According to json-loader README:
Since webpack >= v2.0.0, importing of JSON files will work by default
So if you are using webpack >= v2.0.0 and json-loader together, the file will be transformed twice which caused the issue. The solution is simply delete the json-loader rule.

I was importing the titles.json the wrong way in lib.js
We can do it as follows:
In lib.js
var greetings = require('./titles.json')
And it will be utilized as follows:
{greetings.hello}

Related

Module parse failed: Unexpected token Reactjs?

Module parse failed: Unexpected token Reactjs?
ERROR in ./src/index.js 6:4
Module parse failed: Unexpected token (6:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|
| ReactDOM.render(
<App />,
| document.getElementById('app')
| );
# multi ./src/index.js main[0]
i 「wdm」: Failed to compile.
index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App.jsx';
ReactDOM.render(
<App />,
document.getElementById('app')
);
webpack.config.js
module.exports = {
entry: [
'./src/index.jsx'
],
output:{
path: __dirname,
filename: 'app/js/main.js'
},
module:{
rules: [
{ test: /\.css$/, use: 'css-loader' },
{ test: /\.ts$/, use: 'ts-loader' },
]
}
}
The message is quite clear that you haven't setup the loader to transpile your jsx file yet. Your config file doesn't cover for jsx? file but you did for ts file. The solution is just either add babel + babel-loader to your project or switch file to ts format would resolve your issue.
Here is the basic steps if you go for babel anyway:
Install packages needed:
npm i -D #babel/core #babel/cli #babel/preset-env #babel/preset-react babel-loader
Add babel loader to webpack config:
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader',
options: {
presets: [
"#babel/env",
"#babel/react"
]
},
},
},
]

Webpack bundle is not exported and can't be imported

I created my react Project A using Create-React-app. Then I bundle it them with Webpack and saved in my Git account.
Now I create another project(Called it Project B)in different directory. Download Project A directly from git. And trying to use it like so:
import React from 'react';
import ReactDOM from 'react-dom';
import { Main } from 'project-A/dist/main'
ReactDOM.render(<Main />, document.getElementById('root'));
I am getting an error like following:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
The webpack from Project A looks like this:
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const nodeExternals = require("webpack-node-externals");
module.exports = [
{
/*Client Side*/
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: {
loader: "html-loader",
options: { minimize: true }
}
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader,"css-loader"]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./public/index.html",
filename:"./index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename:"[id].css"
})
]
}
]
I have research through the github and tried to change the name import, it still does not work.
Project A's component looks like this:
App.js:
render() {
return (
<div>
{this.renderCodeAuthCard()}
{this.renderConfirmCard()}
{this.renderVerifyCard()}
</div>
);
}
export default App;
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
Apparently webpack is not exporting the bundle file that is created in Project A. Since the import yields "undefine".
I am trying to find a way to export my webpack bundle file and use it in another project.
Any help will be appreciated
Its because you are not exporting any thing from index.js of Project A. The libraries installed by npm export functions from index.js.

No loading/serving of stylesheets - react

I am attempting SSR with React router's StaticRouter.
express.js (server)
const html = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
res.status(200).send(`
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/app.css" type="text/css"/>
</head>
<body>
<div id="app">${html}</div>
</body>
</html>
`);
Serving of static files:
app.use(express.static(path.resolve(__dirname, "../dist/client")));
App.js (shared)
import React from "react";
import { Switch, Route } from "react-router";
export default () => {
return (
<Switch>
...
</Switch>
);
};
index.jsx (client)
import React from "react";
import { BrowserRouter } from "react-router-dom";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(
<BrowserRouter>
<App/>
</BrowserRouter>,
document.getElementById("app")
);
./styles/Main.scss
.header {
background-color: #002933;
}
I have 2 webpack configurations, 1 for the client & 1 for the server:
webpack.config.dev.js
const nodeExternals = require("webpack-node-externals");
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
devtool: "cheap-module-eval-source-map",
entry: {
app: [
"eventsource-polyfill",
"webpack-hot-middleware/client",
"webpack/hot/only-dev-server",
"react-hot-loader/patch",
"./client/index.jsx",
],
vendor: [
"react",
"react-dom",
],
},
output: {
path: `${__dirname}/dist/client`,
...
},
...
module: {
loaders: [
...
}, {
test: /\.scss$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
{
loader: "css-loader",
query: {
localIdentName: "[hash:8]",
modules: true
}
}, {
loader: "postcss-loader"
}, {
loader: "sass-loader"
}
]
}),
},
],
},
plugins: [
new ExtractTextPlugin({
filename: "[name].css",
allChunks: true
}),
]
};
webpack.config.server.js
const ExternalsPlugin = require("webpack-externals-plugin");
module.exports = {
...
output: {
path: `${__dirname}/dist/`,
filename: "server.bundle.js",
},
...
resolve: {
...
modules: [
"client",
],
},
module: {
loaders: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: "babel-loader",
}, {
test: /\.scss$/,
loader: 'style-loader!css-loader/locals?module&localIdentName=[name]__[local]___[hash:base64:5]!sass-loader',
},
],
},
plugins: [
new ExternalsPlugin({
type: "commonjs",
include: `${__dirname}/node_modules/`,
}),
],
};
I have a JSX file where the .header should be applied to:
import React from "react";
import Links from "./Links.jsx";
import profilePic from "../../img/brand/profilePic.jpg";
import styles from "../../styles/Main.scss";
export default class Header extends React.Component {
constructor() {
super();
}
render() {
return (
<header className={styles.header}>
<img src={profilePic} alt="Professional Picture"/>
<h5>{this.props.pageName}</h5>
<Links/>
</header>
);
}
}
This throws the error:
TypeError: Cannot read property 'header' of undefined
at Header.render (E:/Documents/Projects/website/client/js/components/Header.jsx:22:30)
at resolve (E:\Documents\Projects\website\node_modules\react-dom\cjs\react-dom-server.node.development.js:2149:18)
at ReactDOMServerRenderer.render (E:\Documents\Projects\website\node_modules\react-dom\cjs\react-dom-server.node.development.js:2260:22)
at ReactDOMServerRenderer.read (E:\Documents\Projects\website\node_modules\react-dom\cjs\react-dom-server.node.development.js:2234:19)
at Object.renderToString (E:\Documents\Projects\website\node_modules\react-dom\cjs\react-dom-server.node.development.js:2501:25)
at E:/Documents/Projects/website/server/config/lib/express.js:204:31
at Layer.handle [as handle_request] (E:\Documents\Projects\website\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (E:\Documents\Projects\website\node_modules\express\lib\router\index.js:317:13)
at E:\Documents\Projects\website\node_modules\express\lib\router\index.js:284:7
at Function.process_params (E:\Documents\Projects\website\node_modules\express\lib\router\index.js:335:12)
at next (E:\Documents\Projects\website\node_modules\express\lib\router\index.js:275:10)
at p3p (E:\Documents\Projects\website\node_modules\lusca\lib\p3p.js:15:9)
at E:\Documents\Projects\website\node_modules\lusca\index.js:59:28
at xframe (E:\Documents\Projects\website\node_modules\lusca\lib\xframes.js:12:9)
at E:\Documents\Projects\website\node_modules\lusca\index.js:59:28
at xssProtection (E:\Documents\Projects\website\node_modules\lusca\lib\xssprotection.js:16:9)
When running the application, webpack reports that the stylesheet has been loaded:
EDIT
Other than an ES6 import, I have attempted to use CommonJS' require() as in MERN but still no look...
When I build my server webpack config, I am now getting the error:
ERROR in (webpack)-dev-middleware/node_modules/mime/index.js
Module not found: Error: Can't resolve './types/standard' in 'E:\Documents\Projects\website\node_modules\webpack-dev middleware\node_modules\mime'
# (webpack)-dev-middleware/node_modules/mime/index.js 4:26-53
# (webpack)-dev-middleware/index.js
# ./server/config/lib/express.js
# ./server/config/lib/app.js
# ./server/server.js
I am not sure if this a red-herring or not in this situation or not but thought it worth mentioning here as I am quite lost. Feel as though I am clutching at straws at this point.
This is my .babelrc:
{
"presets": [
"react",
"es2015",
"stage-0"
],
"plugins": [
"react-hot-loader/babel",
"transform-decorators-legacy"
],
"env": {
"server": {
"plugins": [
[
"css-modules-transform", {
"preprocessCss": "./loaders/sass-loader.js",
"generateScopedName": "[hash:8]",
"extensions": [".scss"]
}
]
]
},
"production": {
"presets": [
"es2015",
"react",
"react-optimize",
"es2015-native-modules",
"stage-0"
]
}
}
}
I was attempting to go back to basics and have my babel handle server-side bundling instead of webpack. This was built from a tutorial for SSR with CSS modules I was kindly linked to by #mootrichard
EDIT 2
A few observations which might help...when using an es6 import for stylesheets:
import styles from "../../styles/Main.scss";
and log styles into the console, it returns undefined (evidence that it cannot find the file for some reason).
When putting the <link> tag in the head for the initial page, the <link> tag is present in the markup but not in the network:
However, when navigating to localhost:8000/app.css, a positive response with the styling is sent back:
If the browser can find the bundled version standalone, then why is it not being loaded in my initial page? (The path is correct)
You're having issues because you're using css-loader/locals but not using ExtractTextPlugin (at least in Development).
https://github.com/webpack-contrib/css-loader/issues/59
Note: For prerendering with extract-text-webpack-plugin you should use css-loader/locals instead of style-loader!css-loader in the prerendering bundle. It doesn't embed CSS but only exports the identifier mappings.
This also explains why you're not able to access the style variable .theHeader.
Also, the error Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:3000/app.css". is a red herring. That is simply the error message you receive if you try to load a stylesheet that doesn't even exist. Which in this case, doesn't appear to be in the directory that you think it is, or isn't actually being generated into a file there.
Since ExtractTextPlugin is disabled in development, its likely that your CSS is only being processed by css-loader/locals. This might not be a problem in production, since it pairs with ExtractTextPlugin but could explain your problems of running this in development.
Update:
In looking into this over a little more, I came across a blog post that I think might help you figure out how to configure your CSS to work how you want. https://medium.com/#mattvagni/server-side-rendering-with-css-modules-6b02f1238eb1
I think the main reason for the complication here is that you're sending over the HTML as a rendered string via ReactDOMServer. So there is no where for webpack to inject a <link> tag into. You might want to consider just having a <link> tag in your header to reference your desired CSS file, since webpack is going to create a single CSS file anyways.
Finally, I highly recommend studying a bit more on webpack, especially since SSR is a newer process and requires doing things a bit differently than many have initially anticipated when webpack was first created.
I think you have an error in your webpack.config json hierarchy for you css/sass loaders. Replace your "loaders" array under module with this "rules" array:
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader']
}),
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
],
},
You can see more examples of ExtractTextPlugin usage here: https://github.com/webpack-contrib/extract-text-webpack-plugin#usage

Using Webpack externals and still allow ES6 style imports?

I'm creating a Chrome Extension and I'm using React and Webpack.
Because this is a Chrome extension, I can use manifest.json to load React and ReactDOM into the browser well before any line of my own code get executed. My understanding is that:
the react.js lib loaded by manifest.json show up as globals, accessible via window.React
webpack externals can be configured so that React and ReactDOM doesn't get bundled
Here are my files:
webpack.config.js
module.exports = {
entry: './index.js',
output: {
filename: 'skinny-bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}
]
},
externals: {
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react'
},
'react-dom': {
root: 'reactDOM'
}
}
}
manifest.json
{
"manifest_version": 2,
"name": "Test Application",
"version": "3.2",
"description": "testing",
"short_name": "some test",
"author": "blah blah",
"content_scripts": [
{
"matches": ["https://www.google.com/*"],
"js": [
"react.js",
"react-dom.js",
"skinny-bundle.js"
],
"run_at": "document_idle"
}
]
}
index.js
import HelloGreeting from './HelloGreeting'
ReactDOM.render(
<HelloGreeting />,
document.getElementById('cst')
)
HelloGreeting.js
// import React from 'react' <----- here is my problem!!!
// functional component test
const Hello = props => {
return (
<div>hello world</div>
)
}
// class component test
class HelloGreeting extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<ul>
<li><Hello /></li>
<li>hello universe</li>
</ul>
)
}
}
export default HelloGreeting
Here lies my problem. I have a simple React Component called HelloGreeting that doesn't work if I keep the import React from 'react' line. If I comment out the import, it actually works because my guess is that webpack just ignores it because React has been defined in webpack externals. If I leave the import statement in , I get a "Uncaught TypeError: Cannot read property 'Component' if undefined" error, possibly because Webpack tries to bundle and messing up with window.React somehow. I made this guess because of what webpack emits with or without the import.
If I comment out the import, webpack emits a smaller bundle:
Hash: 26f1526e2554c828c050
Version: webpack 3.5.5
Time: 80ms
Asset Size Chunks Chunk Names
skinny-bundle.js 5.75 kB 0 [emitted] main
[1] ./HelloGreeting.js 2.5 kB {0} [built]
+ 1 hidden module
If I keep my import, my webpack emits a larger bundle:
Hash: 1fc9353f1fe6dd935744
Version: webpack 3.5.5
Time: 77ms
Asset Size Chunks Chunk Names
skinny-bundle.js 6.05 kB 0 [emitted] main
[1] ./HelloGreeting.js 2.71 kB {0} [built]
+ 2 hidden modules
My question is, what can I do to configure webpack so that I still have my ES6 style imports and still have webpack NOT bundle react.js?
I really want to keep the import statement because these components will be used in future projects and I want to keep this as modular and portable as possible.
It turns out I was over-complicating webpack externals.
Changing from:
externals: {
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react'
},
'react-dom': {
root: 'reactDOM'
}
}
to:
externals: {
react: 'React',
'react-dom': 'ReactDOM'
},
...solved my problem. Now webpack ignores all of my React code and keeps my bundle small.
https://github.com/webpack/webpack/issues/1275 helped me out.

electron, react, webpack "Uncaught SyntaxError: Unexpected reserved word"

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.

Categories