How to prepare react component as external package using webpack? - reactjs

I have react component hosted on github, it is simple wrapper around <table> with few features. I use webpack to build my project. This is webpack config inherited after react-create-app:
module.exports = {
bail: true,
devtool: 'source-map',
entry: {
index: paths.appIndexJs
},
externals : {
react: 'react'
},
output: {
path: paths.appBuild,
filename: 'index.js',
publicPath: publicPath,
library: "ReactSimpleTable",
libraryTarget: "umd"
},
resolve: {
fallback: paths.nodePaths,
extensions: ['.js', '.json', '.jsx', '']
},
module: {
preLoaders: [
... preloaders ...
],
loaders: [
... loaders ...
]
},
plugins: [
new webpack.DefinePlugin(env),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.DedupePlugin(),
new ExtractTextPlugin('static/css/[name].[contenthash:8].css'),
],
node: {
fs: 'empty',
net: 'empty',
tls: 'empty'
}
};
And now when I used my component in another project (as external package from github) I've got warnings related to that issue: https://facebook.github.io/react/warnings/dont-call-proptypes.html .
If I remove externals from webpack config everything works fine, but my output file is about 130kB (sic!). With externals in webpack config react is excluded from index.js and it weights about 35kB (non minified). But I got warnings :/
I wonder how to exclude react from build and mitigate warnings. I don't use PropTypes in any unusual way, so advices from https://facebook.github.io/react/warnings/dont-call-proptypes.html are not relevant.
I just want to let users import my component and assume, that they have react already in dependencies...

Related

Module Federation, React, and Apollo 3 warnings

I'm building an app with micro-frontends using webpack 5's module federation plugin. Everything was fine until I started adding react hooks into my remote app. At that point I received errors about "invalid usage of hooks", i.e. I discovered I had TWO versions of react loaded, one from the remote and one from the app consuming the remote.
That problem was solved by adding a shared key to the ModuleFederationPlugin section of my webpack config that marked React as a singleton. Now everything compiles and seems to run just fine.
However, the webpack compiler is throwing some annoying warnings at me now. Its saying:
No required version specified and unable to automatically determine one. Unable to find required version for "react" in description file (/Users/myComputer/Development/myapp/node_modules/#apollo/client/react/context/package.json). It need to be in dependencies, devDependencies or peerDependencies.
Here is what my webpack config (in the remote) looks like currently:
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
const deps = require('./package.json').dependencies
module.exports = {
mode: 'development',
devServer: { port: 3001 },
entry: './src/index.tsx',
output: {
path: __dirname + '/dist/',
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json'],
},
use: 'ts-loader',
},
]
},
devtool: 'source-map',
plugins: [
new ModuleFederationPlugin(
{
name: 'myRemote',
filename: 'remoteEntry.js',
exposes: {
'./App':
'./src/App/App.tsx',
},
shared: {
'react': {
singleton: true,
version: deps['react'],
},
'react-dom': {
singleton: true,
version: deps['react-dom'],
},
},
}
),
new HtmlWebpackPlugin({
template:
'./index.html',
})
]
}
The consuming app's webpack config is almost the same, especially the shared section (there are some slight differences in that it declares the remotes).
What would be the way to tell webpack that the apollo package will be getting its react dependency from somewhere else? Or if thats not the right thing to tell webpack, what is and how can I get rid of these warnings?
Fixed my own problem by changing the key version to requiredVersion

Why Webpack parse less style used by a library in the node_modules and how to prevent that

I'm using the Antd react component library, and our project got bigger over time, so we decided to create a costume Webpack workflow to optimize the build time. the problem is Webpack parse Antd components and try to resolve .less file which is used by Antd and I don't use it in my project at all, and I don't customize Antd theme neither.
How should I config Webpack to avoid parsing Antd library and anything in node_modules?
this is my webpack.dev.config.ts file:
import path from "path";
import { Configuration } from "webpack";
import HtmlWebpackPlugin from "html-webpack-plugin";
const config: Configuration = {
mode: "development",
devtool: "inline-source-map",
entry: "./src/index.tsx",
target: ["browserslist"],
output: {
publicPath: "/",
},
module: {
rules: [
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
exclude: path.resolve(__dirname, "node_modules"),
use: [
{
loader: "ts-loader",
options: {
transpileOnly: true,
},
},
],
},
{
test: /\.css$/i,
exclude: path.resolve(__dirname, "node_modules"),
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: true,
importLoaders: 1,
},
},
{
loader: "postcss-loader",
},
],
},
{
test: /\.svg$/,
exclude: path.resolve(__dirname, "node_modules"),
use: [
{
loader: "svg-url-loader",
options: {
limit: 10000,
},
},
],
},
],
},
resolve: {
modules: ["node_modules"],
extensions: [
".js",
".ts",
".tsx",
".json",
".jsx",
],
},
plugins: [
new HtmlWebpackPlugin({
template: "public/index.html",
}),
],
devServer: {
static: path.join(__dirname, "build"),
historyApiFallback: true,
hot: true,
port: 4000,
open: true,
},
};
export default config;
As far as I can tell from the Webpack config above, you're not parsing anything from node_modules. The only issue I can see might be that this resolved path is incorrect (depends on where this configuration resides in relation to node_modules):
exclude: path.resolve(__dirname, "node_modules")
At which point, all node_modules might be transpiled by ts-loader (and the other loaders) if the path is incorrect.
On that note, since you haven't set up a less loader rule in Webpack to handle antd less files, the only thing you'll be importing from the antd library would be the unstyled JS files.
For example, if you visit the Your First Example within the antd documentation, you'll only see styled antd components when you import "antd/dist/antd.css";:
Otherwise, when you comment out the antd CSS import, the antd components become unstyled:
If you don't see the same result as above with your Webpack configuration, then it's likely that your exclude paths are incorrect or you have an import to node_modules within your code-base that points to a style directory within an antd component -- as is, none of the files within the root directory of a date-picker component (shown below) have an import/require statement that points to the style directory and, as a result, should be unstyled when imported within your code-base:

React component via custom npm package. module cannot be found

I am trying to create a custom npm package that will allow me to import some of my components over multiple projects. I wrote a simple package yesterday which can be found here: demo npm package. It's a simple starter project that has a webpack config and a uses npx babel to transpile and copy the files to the dist and lib folder.
If I include this package into my own project it works but not as I would expect. when I use the following code:
import {NavBar, HelloLib} from "testprivatenprodney;
It gives an error "Module not found".
when I use
import { NavBar, HelloLib } from "testprivatenprodney/lib/HelloLib";
it works as long as the navBar component does not have any child components. If it has I get "Module not found" error again.
I think I am missing something in my webpack configuration. yet all I can find is to have the resolve array, which is included.
const webpack = require("webpack");
module.exports = {
devtool: "source-map",
entry: "./src/index.js",
output: {
path: __dirname + "/dist",
publicPath: "/",
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ["babel-loader"]
},
{
test: /\.css$/,
loaders: ["style-loader", "css-loader"]
}
]
},
resolve: {
extensions: [".js", ".jsx"]
},
plugins: [
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify("production")
}
})
]
};
any help would be much appreciated.

Webpack: Can I get a source map for after babel, before minification?

I have a fairly basic webpack setup that runs babel and out comes my minified js with a source map.
Now when I run my source map in chrome I get the js before babel and before minification. However I would often like to have my source map after babel but before minification. Is this possible?
TL;DR I want source map to post-babel pre-minifcation. Possible?
For completeness
I run babel-loader 8 with webpack 4
Here is a screenshot from chrome showing the problem. As you can see the Dropzone tag indicates this is jsx (and so before babel)
Secondly here is my webpack config (not that it actually matters for my question).
const path = require('path');
module.exports = {
context: path.join(__dirname, 'Scripts', 'react'),
entry: {
client: './client'
},
output: {
path: path.join(__dirname, 'Scripts', 'app'),
filename: '[name].bundle.min.js'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
plugins: [require('#babel/plugin-proposal-object-rest-spread')],
presets: ["#babel/es2015", "#babel/react", "#babel/stage-0"]
}
}
}
]
},
resolve: {
extensions: ['.js', '.jsx']
},
externals: {
// Use external version of React (from CDN for client-side, or
// bundled with ReactJS.NET for server-side)
react: 'React'
},
devtool: 'source-map'
};
Running webpack with -d gives a second set of source maps in chrome that does the trick.

webpack can't build typescript react

I'm trying to build a typescript react project with webpack. I followed the typescript Tutorial, but keep getting the error `module parse failed: ... you may need an appropriate loader``
I can compile using tsc so the problem isn't in typescript itself.
The failure occurs at the <div> in the following snippet
ReactDOM.render(
<div>Something</div>,
document.getElementById("content")
);
If I replace the <div> with null, webpack compiles.
I'm not sure what I'm missing here, I'm guessing it's something with how jsx/tsx is loaded?
My webpack.config is
module.exports = {
entry: "./src/components/index",
output: {
filename: "bundle.js",
path: __dirname + "/dist"
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
extensions: ['.ts', '.tsx', '.js']
},
module: {
rules: [
// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
{
test: /\.tsx?$/,
use: 'awesome-typescript-loader',
}
]
},
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
},
};
----------- update ----------------
React and React-Dom are included in the file index.tsx as
import * as React from "react";
import * as ReactDOM from "react-dom";
JSX is enabled in the tsconfig file as "jsx": "react"
Also, .babelrc includes
{
"plugins": ["transform-runtime","array-includes"],
"presets" : ["env", "react", "stage-2"]
}
----------- update 2 --------------
I suspect this is an issue with webpack loader not loading propertly.
If I change the loader from
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
to
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "some-random-loader-name" },
I would expect it to error that the loader can't be found, but I still get the same behaviour as I did when using awesome-typescript-loader.
This is silly, but just in case anybody else is having a similar issue.
I had an entry in my package.json for a serverless module which included an older version of webpack.
Rather than using the global version, webpack was using the old version but not reporting errors.
I checked my npm list webpack -g, but not npm list webpack

Resources