Webpack, Node.js workflow setup - JS not working properly - javascript

I'm having some problems with JavaScript and actually the way it works on my setup.
When the .js file is inserted directly at the bottom of HTML page then all scripts works as they should. when the file is imported like this:
import "./modules/toDoList"
then I'm getting errors in the console, screenshot of this error is attached at the bottom.
My webpack setup looks like this:
const currentTask = process.env.npm_lifecycle_event
const path = require('path')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const HtmlWebpackPlugin = require("html-webpack-plugin")
const fse = require("fs-extra")
const postCSSPlugins = [
require("postcss-import"),
require("postcss-mixins"),
require("postcss-simple-vars"),
require("postcss-nested"),
require("autoprefixer")
]
class RunAfterCompile {
apply(compiler) {
compiler.hooks.done.tap("Copy images", function() {
fse.copySync("./app/assets/images", "./docs/assets/images") //changed dist to docs for git
})
}
}
let cssConfig = {
test: /\.css$/i,
use: ["css-loader?url=false", { loader: "postcss-loader", options: { postcssOptions: { plugins: postCSSPlugins } } }]
}
let pages = fse.readdirSync("./app").filter(function(file) {
return file.endsWith(".html")
}).map(function(page) {
return new HtmlWebpackPlugin({
filename: page,
template: `./app/${page}`
})
})
let config = {
entry: './app/assets/scripts/App.js',
plugins: pages,
module: {
rules: [
cssConfig
]
}
}
if (currentTask == "dev") {
cssConfig.use.unshift('style-loader')
config.output = {
filename: "bundled.js",
path: path.resolve(__dirname, "app") //generating absolute path
}
config.devServer = {
onAfterSetupMiddleware: function(app, server) {
watchFiles: ("./app/**/*.html") // /**/ any folder if nessesery, /* any html file
},
static: {
directory: path.join(__dirname, "app"),
},
hot: true, //Injecting JSS and CSS to the browser memory on the fly / Hot Module Replacement
port: 3005,
host: '192.168.1.11'
}
config.mode = "development"
}
if (currentTask == 'build') {
config.module.rules.push({
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"]
}
}
})
cssConfig.use.unshift(MiniCssExtractPlugin.loader)
config.output = {
filename: '[name].[chunkhash].js',
chunkFilename: '[name].[chunkhash].js',
path: path.resolve(__dirname, 'docs') //changed dist to docs for git
}
config.mode = 'production'
config.optimization = {
splitChunks: {chunks: 'all'},
minimize: true,
minimizer: [`...`, new CssMinimizerPlugin()]
}
config.plugins.push(
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({filename: 'styles.[chunkhash].css'}),
new RunAfterCompile()
)
}
module.exports = config
My package.json file looks like this:
{
"name": "to-do-list",
"version": "1.0.0",
"scripts": {
"dev": "webpack serve",
"build": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"axios": "^0.21.1",
"html-webpack-plugin": "^5.5.0",
"lazysizes": "^5.3.0",
"lodash": "^4.17.20",
"normalize.css": "^8.0.1"
},
"devDependencies": {
"#babel/core": "^7.20.12",
"#babel/preset-env": "^7.20.2",
"autoprefixer": "^10.2.4",
"babel-loader": "^9.1.2",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^5.0.1",
"css-minimizer-webpack-plugin": "^4.2.2",
"fs-extra": "^11.1.0",
"mini-css-extract-plugin": "^1.3.5",
"postcss-import": "^14.0.0",
"postcss-loader": "^5.0.0",
"postcss-mixins": "^7.0.2",
"postcss-nested": "^5.0.3",
"postcss-simple-vars": "^6.0.2",
"style-loader": "^2.0.0",
"webpack": "^5.20.0",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^4.11.1"
}
}
This is my App.js file:
import "../styles/style.css"
import 'lazysizes'
import "./modules/toDoList"
if (module.hot) {
module.hot.accept()
}
And my folder structure is like per image below:
This is the simple .js to do list app code:
let ourForm = document.getElementById("ourForm")
let ourField = document.getElementById("ourField")
let ourList = document.getElementById("ourList")
ourForm.addEventListener("submit", (e) => {
e.preventDefault()
createItem(ourField.value)
})
function createItem(x) {
let ourHTML = `<li>${x} <button onclick="deleteItems(this)">Delete</button> </li>`
ourList.insertAdjacentHTML("beforeend", ourHTML)
ourField.value = ""
ourField.focus()
}
function deleteItems(elementToDelete) {
elementToDelete.parentElement.remove()
}
This is html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Marius® Web Developer</title>
<link href='https://fonts.googleapis.com/css2?family=Montserrat:wght#100;200;300;400;500;600;700;800;900' rel='stylesheet' type='text/css'>
</head>
<body>
<div class="content-wrapper">
<div class="todo">
<h1>To-Do App</h1>
<form id="ourForm">
<input type="text" autocomplete="off" name="" id="ourField">
<button>Create Item</button>
</form>
<h3>Need To Do</h3>
<ul id="ourList">
</ul>
</div>
</div>
<!-- <script src="assets/scripts/modules/toDoList.js"></script> -->
</body>
</html>
And this is the error in console when I try to delete the item from the list:
With this setup I'm also having problem with mixins, basically they works fine but VS code is marking them as an error as below:
Can anyone help me with this please? The most important thing is why JS is not working as it should. Like I've said it works when .js file is imported directly at the bottom of html page.

Related

Event handling is not working in a fresh react project

I've been trying my first steps with react.js and after playing around a bit (installing Bootstrap, adding some loaders for LESS & Co.) at some point the event handlers (onSubmit, onChange) stopped working. At first, I thought I just messed up my code.
However, when I copy the example for a controlled components form into a freshly initialized npm project with React 17.0.2, these handlers are still not working as expected. E.g. the onSubmit handler:
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
Neither does the alert show, nor is the default event handling prevented. The page simply reloads when I hit the submit button.
For example, if I put an alert into the constructor it is being shown.
Here is the full package.json
{
"name": "app-retry",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack",
"start": "webpack-dev-server --open",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"#babel/core": "^7.16.12",
"#babel/preset-env": "^7.16.11",
"#babel/preset-react": "^7.16.7",
"babel-loader": "^8.2.3",
"html-webpack-plugin": "^5.5.0",
"webpack": "^5.67.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.3"
}
}
and here is the full webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, 'src', 'index.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
dev: {
hot: true,
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// attach the presets to the loader (most projects use .babelrc file instead)
presets: ["#babel/preset-env", "#babel/preset-react"]
}
}
]
},
plugins: [new HtmlWebpackPlugin({ template: path.resolve(__dirname, 'src', 'index.html') })]
};
The index.js is
import React from "react";
import ReactDOM from "react-dom";
// lines as copied from the react example
ReactDOM.render(
<NameForm />,
document.getElementById('root')
);
and finally the index.html template
<html>
<head>
<title>Hello world App</title>
</head>
<body>
<div id="root"></div>
<script src="./bundle.js"></script>
</body>
</html>
What am I doing wrong? Is the example code wrong or is there a flaw in my setup?

Webpack: Loading index.html - Module build failed, Unknown: Unexpected token (3:61) (import.meta.url)

I am learning webpack js; following an example where the trainer loads an html page from src folder to a destination (dist) folder. I am trying the same thing but on Webpack5. I have created a config folder and running the below webpack.dev.js from config folder.
Webpack.dv.js
const path = require("path");
module.exports = {
entry: {
main: ["./src/main.js"]
},
mode: "development",
output: {
filename: "[name]-bundle.js",
path: path.resolve(__dirname, "../dist"),
publicPath: "/"
},
devServer: {
contentBase: "dist",
overlay: true
},
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader"
}
]
},
{
test: /\.html$/i,
use: [
{
loader: "file-loader",
options: {
name: "[name].html"
}
},
{
loader: "extract-loader"
},
{
loader: "html-loader",
}
]
}
]
}
};
Upon yarn serve --config=config/webpack.dev.js command, I get the following error,
./src/index.html 39 bytes [built] [code generated] [1 error]
ERROR in ./src/index.html
Module build failed (from ./node_modules/extract-loader/lib/extractLoader.js):
SyntaxError: unknown: Unexpected token (3:61)
1 | // Imports
2 | import ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___ from "../node_modules/html-loader/dist/runtime/getUrl.js";
> 3 | var ___HTML_LOADER_IMPORT_0___ = new URL("./main-bundle.js", import.meta.url);
| ^
4 | // Module
5 | var ___HTML_LOADER_REPLACEMENT_0___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___);
6 | var code = "<!DOCTYPE html>\n<html>\n <head>\n <title>Testing Webpack with Yarn!</title>\n </head>\n <body>\n <div class=\"profile\">\n <h1>Hello World!</h1>\n </div>\n <script src=\"" + ___HTML_LOADER_REPLACEMENT_0___ + "\"></script>\n </body>\n</html>";
at Parser.pp$5.raise (/Users/syedahmedhussain/Documents/workspaces/Webpack/YarnWebpackMix/node_modules/babylon/lib/index.js:4454:13)
at Parser.pp.unexpected (/Users/syedahmedhussain/Documents/workspaces/Webpack/YarnWebpackMix/node_modules/babylon/lib/index.js:1761:8)
at Parser.pp$3.parseExprAtom (/Users/syedahmedhussain/Documents/workspaces/Webpack/YarnWebpackMix/node_modules/babylon/lib/index.js:3627:50)
at Parser.pp$3.parseExprSubscripts (/Users/syedahmedhussain/Documents/workspaces/Webpack/YarnWebpackMix/node_modules/babylon/lib/index.js:3494:19)
So I played around with the Script tag in the HTML file (given below),
<!DOCTYPE html>
<html>
<head>
<title>Testing Webpack with Yarn!</title>
</head>
<body>
<div class="profile">
<h1>Hello World!</h1>
</div>
<script src="main-bundle.js"></script>
</body>
</html>
Turns out if I remove the <script> tag, the project builds fine but nothing is copied over to dist folder. Can someone please point out as to what is wrong with the above configurations? What am I missing or what can I do to make this work? Also please point out why is it a good or bad idea to load an index.html from a src?
package.json:
{
"name": "name-this-anything",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "webpack serve --config=config/webpack.dev.js"
},
"devDependencies": {
"css-loader": "^5.2.5",
"extract-loader": "^5.1.0",
"file-loader": "^6.2.0",
"html-loader": "^2.1.2",
"style-loader": "^2.0.0",
"webpack": "^5.37.1",
"webpack-cli": "^4.7.0",
"webpack-dev-middleware": "^4.3.0",
"webpack-dev-server": "^3.11.2"
}
}
Thanks!

SyntaxError: Import React from 'react' Unexpected identifier

I'm trying to run my server.js file locally but every time I try "node server.js" I get a:
SyntaxError: Unexpected Identifier for "import React from react
I'm simply trying to see if I get a console.log("connected") message in a function that accesses my database.
I have already tried adding the "transform-es2015-modules-amd" to my plugins in the package.json file in the Babel section. I have tried almost every other solution offered on Stack Overflow posts similar to mine.
package.json
{
"dependencies": {
"atob": "^2.1.2",
"axios": "^0.19.0",
"babel-loader": "^8.0.0-beta.6",
"babel-upgrade": "^1.0.1",
"btoa": "^1.2.1",
"concurrently": "^5.0.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"mysql": "^2.17.1",
"node-fetch": "^2.6.0",
"react": "^16.11.0",
"react-dom": "^16.11.0",
"react-redux": "^7.1.1",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"redux": "^4.0.4",
"request": "^2.88.0",
"serialize-javascript": "^2.1.0"
},
"devDependencies": {
"#babel/cli": "^7.6.4",
"#babel/core": "^7.6.4",
"#babel/node": "^7.6.3",
"#babel/preset-env": "^7.6.3",
"#babel/preset-react": "^7.6.3",
"#types/node": "^12.11.2",
"babel-loader": "^8.0.6",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"css-loader": "^3.2.0",
"nodemon": "^1.19.4",
"style-loader": "^1.0.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.9.0",
"webpack-node-externals": "^1.7.2"
},
"babel": {
"presets": [
"#babel/preset-react",
"#babel/preset-env"
]
"plugins": [
"transform-es2015-modules-amd"
]
}
}
server.js
import React from 'react';
import { StaticRouter } from 'react-router-dom';
import { Provider as ReduxProvider } from "react-redux";
import App from '../client/src/App.js';
import { renderToString } from "react-dom/server";
import createStore, { initialize, fetchCharacters } from './store.js';
var path = require("path");
var express = require("express");
var serialize = require("serialize-javascript");
var db = require('./db');
const PORT = process.env.HTTP_PORT || 4001;
const app = express();
app.use('/static', express.static(path.join(__dirname, 'public')));
console.log(__dirname);
app.get('/*', function(req, res) {
const context = {};
const store = createStore();
store.dispatch(initialize());
Promise.all([store.dispatch(fetchCharacters())]).then(() => {
const component = (
<ReduxProvider store={store}>
<StaticRouter location={req.url} context={context}>
<App/>
</StaticRouter>
</ReduxProvider>
);
const ss_react = renderToString(component);
const ss_state = store.getState();
res.writeHead( 200, { "Content-Type": "text/html" });
res.end(htmlTemplate(component, ss_state));
});
});
function htmlTemplate(component, ss_state) {
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>React SSR</title>
</head>
`;
}
app.listen(PORT, () => {
console.log(`server listening at port ${PORT}. `);
});
webpack.config.js
const webpack = require('webpack')
const nodeExternals = require('webpack-node-externals')
const path = require('path')
const js = {
test: /\.m?(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader'
}
}
const css = {
test: /\.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: true
}
}
]
}
const serverConfig = {
mode: 'development',
target: 'node',
node: {
__dirname: false
},
externals: [nodeExternals()],
entry: {
'index.js': path.resolve(__dirname, 'server/server.js')
},
module: {
rules: [js]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name]'
}
}
const clientConfig = {
mode: 'development',
target: 'web',
entry: {
'index.js': path.resolve(__dirname, 'client/src/index.js')
},
module: {
rules: [js, css]
},
optimization: {
splitChunks: {
chunks: 'all'
}
},
output: {
path: path.resolve(__dirname, 'dist/public'),
filename: '[name]'
}
}
module.exports = [serverConfig, clientConfig]
Node does not understand React JSX. That's what Webpack is for - it uses Babel to transpile your code into vanilla JavaScript.
Looks like you have webpack-dev-server as a dev dependency, so it should already be installed (if you've done an npm install). Make sure you have something like this in your package.json scripts field:
"scripts": {
"start:dev": "webpack-dev-server --config webpack.config.js"
},
Then run npm run start:dev in your console.

Setting up React with Grails

I'm currently working on integrating React with Grails (2.3.11). It seems however that even the most basic setup is giving me a hard time. I've set up my file and folder structure that I have done before with past projects but my bundle.js file just doesn't seem to be want to be found. I keep getting a 404 no matter how many different times I change the path.
This is basically what happens all the time!
My package.json file:
{
"name": "react_test",
"version": "1.0.0",
"description": "Grails with React",
"main": "index.js",
"license": "MIT",
"dependencies": {
"axios": "^0.18.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-redux": "^5.0.7",
"react-router-dom": "^4.3.1",
"redux": "^4.0.0",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"redux-logger": "^3.0.6",
"webpack": "^4.12.0",
"webpack-cli": "^3.0.8"
},
}
My root.gsp file that is supposed to pick up the bundle.js file and render the react code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Grails with React</title>
<script src="../../../src/react/public/bundle.js"></script>
</head>
<body>
<div id="root">
<p>React broke down</p>
</div>
</body>
</html>
My Webpack file:
var webpack = require('webpack')
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'src/react/public');
var APP_DIR = path.resolve(__dirname, 'src/react/app');
var config = {
entry: APP_DIR + '/main.jsx',
mode : 'development',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module : {
rules : [
{
test : [/\.jsx?$/, /\.js?$/],
exclude: /node_modules/,
include: APP_DIR,
loader : 'babel-loader',
query: {
presets: ['react', 'env']
}
}
]
},
devtool: 'source-map',
resolve: {
extensions: [".js", '.jsx', '*']
}
};
module.exports = config;
Finally here's my simple starting file:
import React from 'react';
import {render} from 'react-dom';
class App extends React.Component {
render () {
return <p> Hello, World!</p>;
}
}
render(<App/>, document.getElementById('root'));
If it helps, here's my folder structure!
Any advice or help you can throw my away is greatly appreciated! I'd be willing to experiment! Thank you!
After a lot of experimentation I discovered what needed to be done. Because this is a Grails application it has be written very specifically and has to be outputted in the correct folder.
Change the script line into this:
<g:javascript src="bundle.js"></g:javascript>
Then make sure to output the bundle.js file in the web-app/js folder. This is a must. So change your webpack to this:
var BUILD_DIR = path.resolve(__dirname, 'web-app/js');
That solved it!

Webpack and Reactjs app not loading html

I'm trying to build an app with reactjs+webpack+babel. My webpack.config.js is:
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'src/client/bin');
var APP_DIR = path.resolve(__dirname, 'src/client/app');
var config = {
context: APP_DIR,
entry: {
vendor: ['react', 'react-dom'],
app: APP_DIR + '/index.jsx'
},
resolve: {
extensions: [".webpack.js", ".web.js", ".js", ".jsx"]
},
output: {
path: BUILD_DIR,
filename: '[name].js'
},
devServer: {
inline:true,
port: 9000
},
module : {
loaders : [
{
test : /\.jsx?/,
exclude: /node_modules/,
include : APP_DIR,
loader : 'babel-loader',
query: {
presets: ['react', 'es2015']
}
}
]
}
};
module.exports = config;
Then my index.jsx is:
import React from 'react';
import {render} from 'react-dom';
class App extends React.Component {
render () {
return <p> Hello React!</p>;
}
}
render(<App/>, document.getElementById('app'));
And my html file:
<html>
<head>
<meta charset="utf-8">
<title>React.js using NPM, Babel6 and Webpack</title>
</head>
<body>
<div id="app"></div>
<script async src="bin/bundle.js" type="text/javascript"></script>
</body>
</html>
And this html is in the bin folder. What am I doing wrong, so when I open throw browser (and webpack server) I don't have that html.
EDIT:
{
"main": "index.jsx",
"scripts": {
"start": "webpack-dev-server --inline --hot",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "André Roque Nº31260",
"license": "ISC",
"dependencies": {
"react": "^0.14.9",
"react-dom": "^0.14.9",
"react-router": "^4.1.1",
"webpack": "^2.5.1"
},
"devDependencies": {
"babel-core": "^6.4.5",
"babel-loader": "^6.2.1",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"html-webpack-plugin": "^2.28.0",
"webpack": "^2.5.1"
}
}
Try serving the contentBase to the devServer from the folder in which the html file is present with you bundled script. You should provide path to the webpack-dev-server such as following example:
devServer: {
contentBase: path.resolve(__dirname, 'src/client/bin'),
inline:true,
port: 9000
},
Hope this helps.

Categories