React hook error when use built package from webpack - reactjs

I've making a library and tried to use built package on example code by doing this
import { createMiddleware, useActionListener } from "../../../../lib";
It occurs an error Invalid hook call. at
useActionListener("SUB", (action) => {
//...
});
So I tried to publish a package and changed like this
import { createMiddleware, useActionListener } from "myLibraryName";
And it works like charm.
I have no idea why calling built package direct occurs an error. Any ideas?
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'lib'),
filename: 'index.js',
libraryTarget: 'umd',
library: 'reactActionListener',
globalObject: 'this',
},
externals: {
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react',
},
redux: {
root: 'Redux',
commonjs2: 'redux',
commonjs: 'redux',
amd: 'redux',
},
},
resolve: {
extensions: ['.ts', '.js', '.json', '.tsx', '.jsx'],
alias: {
// Needed when library is linked via `npm link` to app
react: path.resolve('./node_modules/react'),
},
},
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
module: {
rules: [
{
test: /\.(js|ts|tsx|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
};

Related

After publish react in npm can't load chunks of react.lazy

I have a CRA react project where i'm using react.lazy to split the code. I'm currently working on publish it in npm as a react component.
For compilate the code i'm using Craco. Here is the configuration of it:
const CracoLessPlugin = require('craco-less');
const path = require('path');
const PACKAGE_NAME = 'name'
const CSS_FILE_NAME = 'main.css';
module.exports = {
webpack: {
configure: (webpackConfig, { paths }) => {
const buildFolder = path.resolve(__dirname, 'build');
paths.appBuild = buildFolder;
webpackConfig.externals = {
...webpackConfig.externals,
react: {
commonjs: 'react',
commonjs2: 'react',
amd: 'react',
root: 'React',
},
'react-dom': {
commonjs: 'react-dom',
commonjs2: 'react-dom',
amd: 'react-dom',
root: 'ReactDOM',
}
};
webpackConfig.plugins[5].options.filename = CSS_FILE_NAME;
webpackConfig.plugins[5].options.linkType = 'text/css'
return {
...webpackConfig,
output: {
...webpackConfig.output,
path: buildFolder,
filename: 'main.js',
library: PACKAGE_NAME,
libraryTarget: 'umd',
umdNamedDefine: true,
publicPath: `/`,
},
optimization: {
...webpackConfig.optimization,
runtimeChunk: false,
splitChunks: {
...webpackConfig.optimization.splitChunks,
chunks: 'all',
cacheGroups: {
default: false,
vendors: false,
},
},
},
};
},
},
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
javascriptEnabled: true,
}
}
}
]
};
I managed to publish it correctly but when i'm importing it in other react project, I can't manage to load the chunks. I always got something like this
This is happening for js and css files.
I think that the problem is related to the public_path of the output configuration of webpack, but i can't find the correct value for it to make this work.
I can give you more information about other related configuration if asked.
Thank you for the help.

Resolve fonts from ui components with react + webpack 5

I am creating a library with UI components to share among my react projects. Components are created with React and with Webpack 5. This is the webpack config file:
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/index.js',
mode: 'production',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
libraryTarget: 'umd',
library: 'ui-lib',
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.(png|jpg|gif|svg)$/,
type: 'asset/resource',
},
{
test: /.(ttf|otf|eot|woff(2)?)(\?[a-z0-9]+)?$/,
type: 'asset/resource',
generator: {
filename: '[name][ext]',
},
},
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: false,
},
},
{
loader: 'resolve-url-loader',
options: { sourceMap: true, root: path.resolve(__dirname, 'src') },
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
chunkFilename: '[id].[hash].css',
}),
new webpack.ProvidePlugin({
React: 'react',
}),
],
resolve: {
extensions: ['.js', '.jsx', '.scss'],
modules: ['node_modules', path.resolve(__dirname, 'src')],
},
externals: {
react: 'react',
},
};
This is generating a dist/ folder with this content:
Seems everything is fine. The problem is when using this library in a React project, The components seems ok but fonts are not loaded correctly. The console throughs this message:
Failed to decode downloaded font: http://localhost:3000/static/js/GilroySemiBold-webfont.woff2
Fonts are being downloaded but not sure that files are not corrupt.
So, any clue about how can I use the fonts from the library??? Thanks in advance

Webpack generating [hash].worker.js file when packaging custom library

I'm trying to create a library of reusable react components for our internal use.
Webpack is bundling the output - which should be a single file. But it's actually putting out the bundle.js that I'd expect plus a file called [some_hash].worker.js.
I'm not sure how to force webpack to include that "worker" file with the single bundle that I'm asking it for.
The webpack.config:
const path = require('path');
const webpack = require('webpack');
const DIST_PATH = path.resolve(__dirname, "../dist");
const SRC_PATH = path.resolve(__dirname, "../src");
const APP_PATH = path.resolve(__dirname, "../src/index.js");
const BASE_PATH = path.resolve(__dirname);
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = ({ appPath = APP_PATH, distPath = DIST_PATH }) => ({
context: BASE_PATH,
devServer: {
contentBase: distPath,
compress: true,
port: 9000,
historyApiFallback: true
},
resolve: {
modules: ['node_modules', SRC_PATH],
alias: {
'react': path.resolve(__dirname, '../node_modules/react'),
'react-dom': path.resolve(__dirname, '../node_modules/react-dom'),
}
},
externals: {
// Don't bundle react or react-dom
react: {
commonjs: "react",
commonjs2: "react",
amd: "React",
root: "React"
},
"react-dom": {
commonjs: "react-dom",
commonjs2: "react-dom",
amd: "ReactDOM",
root: "ReactDOM"
}
},
entry: {
bundle: appPath,
},
output: {
path: distPath,
filename: 'index.js',
publicPath: '/dist/',
library: 'internal-components',
libraryTarget: 'umd',
umdNamedDefine: true
},
module: {
rules: [
{
test: /\.jsx$/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react'],
plugins: [
'#babel/plugin-proposal-object-rest-spread',
'#babel/plugin-syntax-dynamic-import',
[ '#babel/plugin-proposal-decorators', { 'legacy': true } ],
[ '#babel/plugin-proposal-class-properties', { 'loose': true } ]
]
}
}
},
{
test: /\.js$/,
exclude: /(node_modules|build)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
plugins: [
'#babel/plugin-proposal-object-rest-spread',
'#babel/plugin-syntax-dynamic-import',
['#babel/plugin-proposal-decorators', {'legacy': true}],
["#babel/plugin-proposal-class-properties", {'loose': true}]
]
}
}
},
...
]
},
plugins: [
new CleanWebpackPlugin(),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
})
]
});
You might try using the worker-loader plugin with inline to handle the bundling -
rules: [
...
{
test: /\.worker\.js$/,
use: {
loader: 'worker-loader',
options: { inline: true, fallback: false }
}
}
]
That said, there are several open issues on Github surrounding using the worker as a blob, so YMMV
Actually if you are using webpack 3 and above, chunking of the bundle is automatically done for you. In the SplitChunks Plugin documentation here it is actually stated how this behaves.
So because of this you might need to scan your code and check for this conditions. Also it's good to know if you are asynchrously importing the some module? That might signal webpack to make it into a separate chunk.

How to split chunks when authoring libraries with webpack 4?

I'm trying to publish a custom react component to a private repository.
I use react-loadable to load a subcomponent on demand. When running locally, everything works fine. The index.js file correctly makes a request to the chunk.js file when needed. However, when published and used from another project, the component hits a 404 error when trying to request the subcomponent chunk.
How am i supposed to split chunks and load them on demand when authoring a library? Is this even possible or am i thinking about it the wrong way?
Here's my webpack.config.js in case it's a simple matter of configuration:
module.exports = () => ({
context: __dirname,
mode: 'development',
entry: './src/index.jsx',
output: {
path: path.join(__dirname, './dist'),
filename: "index.js",
library: "reactcombobox",
libraryTarget: "umd",
publicPath: path.join(__dirname, './dist'),
umdNamedDefine: true
},
plugins: [
new webpack.LoaderOptionsPlugin({ options: { context: __dirname}}),
new CleanWebpackPlugin([path.join(__dirname, './dist')], {verbose: true, allowExternal: true})
],
module: {
rules: [
{
test: /.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['#babel/preset-env', {
"targets": {
"browsers": ["last 4 Chrome versions"]
}
}],
'#babel/preset-react'
],
plugins: [
'#babel/plugin-transform-react-jsx',
'#babel/plugin-proposal-class-properties',
'#babel/plugin-syntax-dynamic-import'
]
}
}
},
{
test: /.css$/,
use: ["style-loader","css-loader"]
}
]
},
externals: {
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react',
},
'react-dom': {
root: 'ReactDOM',
commonjs2: 'react-dom',
commonjs: 'react-dom',
amd: 'react-dom',
}
},
resolve: {
extensions: ['*', '.js', '.jsx']
}
});
if your component no relative please split to more file and use export {a1,a2};
do not use loadable.

Can't import a module in my crafted module

I did a slider on mobx and bundle it using webpack 3. I excluded mobx from slider's bundle using "externals". Then I published it as package, created a mobx-sandbox and installed the slider there.
In result I'm getting an error because package can't import mobx.
But I expecting that slider will find mobx because I imported it on sandbox page.
I also receiving in console:
[mobx] Warning: there are multiple mobx instances active.
This might lead to unexpected results.
What am I missing?
slider's webpack.config:
var path = require('path');
var webpack = require('webpack');
module.exports = {
node: {
fs: "empty" // https://github.com/josephsavona/valuable/issues/9
},
devtool: 'source-map',
entry: {
bundle: [ "./src/index.js" ]
},
output: {
path: path.join(__dirname, "lib"),
filename: "index.js"
},
externals: {
'react': {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react'
},
'react-dom': {
root: 'ReactDOM',
commonjs2: 'react-dom',
commonjs: 'react-dom',
amd: 'react-dom'
},
'mobx': {
root: 'mobx',
commonjs2: 'mobx',
commonjs: 'mobx',
amd: 'mobx'
},
'mobx-react': {
root: 'mobx-react',
commonjs2: 'mobx-react',
commonjs: 'mobx-react',
amd: 'mobx-react'
}
},
stats: {
colors: true,
reasons: true
},
resolve: {
extensions: ['.js']
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /\/node_modules\//,
loader: 'babel-loader',
query: {
cacheDirectory: true
}
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
]
};
slider's .babelrc
{
"presets": ["es2015", "react", "stage-0"],
"plugins": ["transform-decorators-legacy"]
}
slider repository:
https://github.com/andiwilflly/rslider
sandbox repository:
https://github.com/SkunSHD/rslider-test-sandbox
The problem was with absence of umd's imports in bundle.
This line in output helped to import modules in bundle properly:
webpack.config:
module.exports = {
... ,
output: {
... ,
libraryTarget: 'umd'
}
}

Resources