Webpack 5 React component library UMD bundle with SourceMaps - javascript

I am attempting to make a webpack 5 build process to create a react component library I just had a couple of things cannot seem to get working.
#1) The webpack build command works fine, and when using the inline-source-map option I can
SEE the data URL embeded in the outputted build file but when I ever I attempt to publish and test this library on NPM I always get obfuscated errors without original lines of code so I can't even tell where the errors are; what else am I missing to activate source-maps? I am using Chrome dev tools and it doesn't even tell me a source map is available for that code...
#2) Another issue I am having is after building this with webpack into the dist folder; I start another CRA test app and try to pull components out of the built library but all I get are these errors.
./src/dist/index.js
Line 1:1: Expected an assignment or function call and instead saw an expression no-unused-expressions
Line 1:112: 'define' is not defined no-undef
Line 1:123: 'define' is not defined no-undef
Line 1:190: Unexpected use of 'self' no-restricted-globals
Line 1:466: Expected an assignment or function call and instead saw an expression no-unused-expressions
Line 1:631: Expected an assignment or function call and instead saw an expression no-unused-expressions
I am aware webpack 5 stopped bundling polyfills for Node but shouldn't this code run
if I place it in the src directory of a CRA application? This is bundled code shouldn't it work in the browser/ in another React application? I targeted UMD so I thought it would work in this environment
here is all the necessary info
Webpack.config.js
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const nodeExternals = require("webpack-node-externals");
module.exports = {
entry: "./src/index.js",
devtool: "inline-source-map",
externals: [nodeExternals()],
output: {
filename: "index.js",
path: path.resolve(__dirname, "dist"),
library: {
name: "test",
type: "umd",
},
},
plugins: [new CleanWebpackPlugin()],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env", "#babel/preset-react"],
},
},
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"],
include: path.resolve(__dirname, "./src"),
},
],
},
};
Package.json
{
"name": "test-lib",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "start-storybook",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"prop-types": "^15.7.2",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"#babel/core": "^7.15.8",
"#babel/preset-env": "^7.15.8",
"#babel/preset-react": "^7.14.5",
"#storybook/addon-knobs": "^6.3.1",
"#storybook/react": "^6.3.10",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^4.0.0",
"node-sass": "^6.0.1",
"path": "^0.12.7",
"sass-loader": "^12.1.0",
"webpack": "^5.58.0",
"webpack-cli": "^4.9.0",
"webpack-node-externals": "^3.0.0"
}
}
Button.js (sample component)
import React from 'react'
import PropTypes from 'prop-types';
const Button = ({message = 'Hello world'}) => (
<button>{message}</button>
)
Button.propTypes = {
message: PropTypes.string.isRequired
}
export default Button
Build entry point (index.js)
export { default as Button } from "./components/Button";

Related

How do I fix "require is not defined" error with Webpack and Babel?

I keep getting error Uncaught ReferenceError: require is not defined in browser even with Webpack and Babel. For some reason I never had to worry about this before. I'm not sure if this error is caused by updated packages or what. I set up a very simple test application for simplicity.
package.json
{
"name": "require-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"engines": {
"node": "16.16.0"
},
"scripts": {
"build": "webpack --config webpack.config.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/core": "^7.18.10",
"#babel/preset-env": "^7.18.10",
"babel-loader": "^8.2.5",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0"
}
}
webpack.config.js
const path = require('path');
module.exports = {
target: "node",
mode: "production",
output: {
path: path.resolve(__dirname, 'dist'),
clean: true,
filename: (pathData) => {
return 'index.js'
},
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
}
]
}
}
src/index.js (js file before build)
const path = require('path');
console.log(path);
dist/index.js (js file after build)
(()=>{var r,e={17:r=>{"use strict";r.exports=require("path")}},t={};r=function r(o){var s=t[o];if(void 0!==s)return s.exports;var p=t[o]={exports:{}};return e[o](p,p.exports,r),p.exports}(17),console.log(r)})();
There're a few things on your code needing changed. First of all, you can't target to build for node while you run that code on browser which is wrong. Secondly, path is designed and built to run on node server specifically, however, there's a fallback for path on browser though which is called path-browserify. You can check its document to see how it works.
Anyway to sum up, you need to switch target as web in the end:
module.exports = {
target: "web",
// ...
}

Why can't I call fetch on jest with vanilla javascript?

I'm kind of new to testing library, and recently started studying Jest. I'm currently trying to implement vanilla javascript project with jest.
I know 'mocking' an async API call in jest is best practice, but I wanted to actually call API using fetch to see if jest works correctly. But I got stuck on 'fetch' request. Need to remind you that my project is not node project, just plain vanilla javascript project.
Before moving on to actual test code, since I'm using babel and webpack on my project. Here's .bablerc.js and webpack.config.js implementation.
.babelrc.js
module.exports = {
presets: [
[
'#babel/env',
{
targets: {
browsers: ['> 0.25%, not dead'],
},
useBuiltIns: 'usage',
corejs: 3,
shippedProposals: true,
},
],
],
};
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/js/index.js',
output: {
path: path.resolve(__dirname, 'public'),
filename: 'static/js/main.js',
},
module: {
rules: [
{
loader: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/,
},
{
test: /\.(sc|c)ss$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
],
},
devServer: {
contentBase: path.resolve(__dirname, 'public'),
inline: true,
hot: true,
watchOptions: {
poll: true,
ignored: '/node_modules/',
},
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'Typing Game',
minify: {
collapseWhitespace: true,
},
hash: true,
template: './src/index.html',
}),
new MiniCssExtractPlugin({ filename: 'static/css/styles.css' }),
],
};
With project configuration above, webpack and webpack-dev-server worked perfectlly and could retrieve completely built html, css and js files. After checking everything except Jest works perfectly, I implemented simple API call function that gets list of words in array,
export const getWordsAPI = () =>
fetch(
'https://server-api-address'
).then((res) => res.json());
And tried to call the api function on my jest test code.
import { getWordsAPI } from '../src/js/api';
describe('Integration with getWords API', () => {
test('Get Word List', async () => {
const result = await getWordsAPI();
expect(result).toEqual([
{
text: 'hello',
},
{
text: 'world',
}
]);
});
});
But, I continuously got this 'fetch is not defined' error.
ReferenceError: fetch is not defined
> 1 | export const getWordsAPI = () =>
| ^
2 | fetch(
3 | 'https://server-api-address'
4 | ).then((res) => res.json());
at getWordsAPI (src/js/api.js:1:28)
at _callee$ (__tests__/api.test.js:5:26)
at tryCatch (node_modules/regenerator-runtime/runtime.js:63:40)
at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:293:22)
at Generator.next (node_modules/regenerator-runtime/runtime.js:118:21)
at asyncGeneratorStep (__tests__/api.test.js:11:103)
at _next (__tests__/api.test.js:13:194)
at __tests__/api.test.js:13:364
at Object.<anonymous> (__tests__/api.test.js:13:97)
I tried everything to solve this problem, including jest-fetch-mock but couldn't solve the problem. when I applied jest-fetch-mock to test code, I got new error which is this.
invalid json response body at reason unexpected end of json input
I eventually ended up using isomorphic-fetch library to make fetch work on my test code, which makes me uncomfortable.
import 'isomorphic-fetch';
import { getWordsAPI } from '../src/js/api';
describe('Integration with getWords API', () => {
...
}
I understand fetch is not defined error happening on nodejs environment, since there is not fetch provided by node, but this is vanilla javascript project. fetch is provided by default on browser, and should work without any additional work. But why is this error happening? I don't know what is causing this problem, either babel or webpack or even jest itself.
Please teach me what I'm missing. Probably I'm missing the main concept of Jest architecture, related to this problem. Waiting for anyone's response
ps. In case you need to know what version of libraries I'm using in my project, here's my package.json file. Other than libraries, I'm using WSL2 on Windows OS, and using npm instead of yarn.
{
"name": "typing_game",
"version": "1.0.0",
"description": "Typing Game by Vanilla Javascript",
"main": "index.js",
"author": "piecemakerz <piecemakerz#naver.com>",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --open",
"build": "webpack",
"test": "jest"
},
"devDependencies": {
"#babel/core": "^7.12.3",
"#babel/preset-env": "^7.12.1",
"#types/jest": "^26.0.15",
"babel-jest": "^26.6.3",
"babel-loader": "^8.2.1",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^5.0.1",
"html-webpack-plugin": "^4.5.0",
"jest": "^26.6.3",
"mini-css-extract-plugin": "^1.3.1",
"prettier": "^2.1.2",
"sass-loader": "^10.1.0",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0"
},
"dependencies": {
"core-js": "^3.7.0",
"isomorphic-fetch": "^3.0.0",
"sass": "^1.29.0"
},
"jest": {
"transform": {
"^.+\\.js?$": "babel-jest"
}
}
}

Webpack css-loader: "Module not found: Error: Can't resolve 'main.css' in ..."

I am trying to include my css in the server hosted by webpack-dev-server. For that to happen, I apparently have to use style-loader and css-loader together, in order to bundle the css into the JavaScript.
I can't get it to work.
I follow the instructions here, yet I get the following error:
ERROR in ./src/index2.js
Module not found: Error: Can't resolve 'main.css' in C:\Users\magnusga\Downloads\Programming\TestPrograms\test\src'
# ./src/index2.js 1:0-27
# multi (webpack)-dev-server/client?http://localhost:8080 ./src/index2.js
I know for certain that main.css is in the same folder as index2.js
My Settings
index2.js
import css from 'main.css';
// ...much more code
webpack.config.js
module.exports = {
entry: {
app: './src/index2.js'
},
devtool: 'inline-source-map',
devServer: {
contentBase: './dist'
},
module: {
rules: [
{
test: /\.css$/,
exclude: /node_modules/,
use: ['style-loader', 'css-loader']
}
],
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Development',
template: 'src/index.html',
inject: 'head'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
package.json
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index2.js",
"dependencies": {
"rxjs": "^5.5.6"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"clean-webpack-plugin": "^0.1.17",
"css-loader": "^0.28.11",
"extract-text-webpack-plugin": "^3.0.2",
"html-webpack-plugin": "^2.30.1",
"postcss-loader": "^2.1.3",
"sass-loader": "^6.0.7",
"style-loader": "^0.20.3",
"webpack": "^3.10.0",
"webpack-dev-server": "^2.11.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"buildb": "babel src --watch --out-dir built --copy-files",
"watch": "webpack --watch",
"start": "webpack-dev-server",
"build": "webpack"
},
"author": "",
"license": "ISC"
}
One Fix
One fix is to use import css from './main.css'; instead of import css from 'main.css'; (note the ./ infront of the file name).
That does not feel right though, because the css-loader site shows that it should be the latter, not the former.
Is it a typo in the docs?
Thank you.
It is not really a typo. If you import it like this:
import css from 'main.css';
Webpack thinks, that you want to import a module, and searches for this file under node_modules. This is necessary, when you for example installed the bootstrap package and want to import its css. So when your css file comes from a dependency, you import that dependency like this. But when you want to import a lokal file, always use relative paths.
So it must be: import css from './main.css';
Further Reading:
https://webpack.js.org/concepts/module-resolution/#module-paths
https://webpack.js.org/configuration/resolve/#resolve-modules

Can't resolve "app.js" - Webpack

Problem
So, i'm working a web app using Webpack and ES6. When I try to run Webpack, it tells me that it can't resolve "app.js". I've looked all across the internet for a solution, but I just couldn't find one, can someone help me?
The Full error is:
ERROR in ./assets/js/main.js
Module not found: Error: Can't resolve 'app.js' in 'C:\Users\sidna\Dropbox\Dev Stuff\Web Apps\Mondrian Generator\assets\js'
# ./assets/js/main.js 4:0-17
webpack.config.js
module.exports = {
entry: './assets/js/main.js',
output: {
filename: 'assets/js/build.js',
},
watch: true,
module: {
loaders: [
{
test: /\.scss$/, loader: "style-loader!css-loader!sass-loader"
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
}
],
}
};
app.js (Empty)
main.js
// SCRIPTS
require("app.js");
// STYLES
require("../css/large.scss");
package.json
{
"name": "mondrian-generator",
"version": "1.0.0",
"description": "Create your own Mondrian",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "ISC",
"dependencies": {
"css-loader": "^0.28.0",
"style-loader": "^0.16.1",
"webpack": "^2.4.1"
},
"devDependencies": {
"babel-core": "^6.24.1",
"babel-loader": "^6.4.1",
"babel-preset-env": "^1.4.0",
"node-sass": "^4.5.2",
"sass-loader": "^6.0.3",
"script-loader": "^0.7.0",
"webpack": "^2.4.1"
}
}
When the import is neither an absolute path (starting with /) nor explicitly a relative path (starting with ./ or ../), it is resolved as a module, which means it's Loading from node_modules Folders.
Your app.js is not in node_modules, so you need to change it to a relative path (assuming it's in the same directory as main.js):
require("./app.js");
Webpack follows the import behaviour of Node.js, but it also allows you to change it with the resolve.modules option.

Simple Webpack + React + ES6 + babel example doesn't work. Unexpected token error

am getting a parsing error while running webpack to compile the jsx syntax. Would appreciate if someone could point me to the error. I see a similar question asked Webpack, React, JSX, Babel - Unexpected token < but the solution suggested there doesn't work for me.
This is how my config files look like:
package.json
{
"name": "dropdowns",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"react": "^15.2.1",
"react-dom": "^15.2.1",
"babel-core": "^6.11.4",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.11.1"
},
"devDependencies": {
"webpack": "^1.13.1",
"webpack-dev-server": "^1.14.1"
},
"author": "",
"license": "ISC"
}
my webpack.config.js file is
module.exports = {
context: __dirname + "/app",
entry: "./main.js",
output: {
filename: "bundle.js",
path: __dirname + "/dist"
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
}
]
}
};
In a local app folder I have main.js and IdMappingOptions.js as follows:
// in IdMappingOptions.js
import React from 'react';
class IdMappingOptions extends React.Component {
render () {
return <span>Hello!</span>
}
}
export default IdMappingOptions;
// in main.js
import React from 'react';
import { render } from 'react-dom';
import IdMappingOptions from './IdMappingOptions';
render(
<IdMappingOptions/>, document.body
);
when running node_modules/.bin/webpack I get the following error trace:
Hash: 396f0bfb9d565b6f60f0
Version: webpack 1.13.1
Time: 37ms
[0] ./main.js 0 bytes [built] [failed]
ERROR in ./main.js
Module parse failed: /scratch/parallel/repository/dropdowns/app/main.js Unexpected token (6:4)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (6:4)
at Parser.pp.raise (/scratch/parallel/repository/dropdowns/node_module/acorn/dist/acorn.js:923:13)
Edit:
as per the comments below fixed the test pattern and added babel-core in the webpack.config.js. Here is my
Your test seems faulty:
test: "/.js$"
Try this:
test: /\.js$/
You need babel-core to use babel in your project. (https://github.com/babel/babel-loader#installation).
npm install --save-dev babel-core

Categories

Resources