I am trying to use a component library that I created to reuse in other projects. In it I used loadable-components with webpack and code splitting.
But, when importing into a Next.js project, errors are returned, showing that you cannot import the component from that library.
I have two projects:
Project A = Component library
Project B = Will import Project A
Project B that imported the library (Project A):
(node:20271) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'SomeComponent' of undefined
Config of the imported library (Project A):
webpack.build.config.js
module.exports = {
...
entry: {
[packageName]: './src/index.js'
},
target: 'web',
output: {
chunkFilename: '[chunkhash].chunk.js',
library: packageName,
libraryTarget: 'commonjs2',
globalObject: 'this'
},
externals: nodeExternals(),
optimization: {
minimize: true,
usedExports: true,
splitChunks: {
chunks: 'all',
},
},
plugins: [
new LoadablePlugin()
],
...
}
src/index.js
import styled, { ServerStyleSheet, createGlobalStyle } from 'styled-components';
export * from '#components';
export * from '#style';
export { default as Icons } from '#assets/icons';
export { styled, ServerStyleSheet, createGlobalStyle };
Above, only the #components folder has loadable-components
.babelrc
{
"plugins": [
"styled-components",
[
"#babel/plugin-proposal-pipeline-operator",
{
"proposal": "minimal"
}
],
[
"#babel/plugin-proposal-optional-chaining",
{
"loose": false
}
],
[
"#babel/plugin-proposal-class-properties",
{
"loose": true
}
],
"#loadable/babel-plugin"
]
}
In the Project B, I only import this library with the generated chunks.
But, the same error is always shown, regardless of whether the component is loaded on demand or not.
What am I doing wrong? Any suggestion?
Thanks!
Related
I'm maintaining a react component library that uses chart.js as a dependency (Not peerDependency).
I upgraded chart.js from 3.9.1 to 4.0.1.
My library still compiles fine but now it throws an error on my react app when I'm importing the lib :
Module not found: Error: Package path . is not exported from package node_modules/chart.js
I'm building everything with rollup here is my config :
import path from 'path';
import babel from '#rollup/plugin-babel';
import commonjs from '#rollup/plugin-commonjs';
import resolve from '#rollup/plugin-node-resolve';
import terser from '#rollup/plugin-terser';
import postcss from 'rollup-plugin-postcss';
import typescript from '#rollup/plugin-typescript';
import image from '#rollup/plugin-image';
import json from '#rollup/plugin-json';
import copy from 'rollup-plugin-copy';
import autoprefixer from 'autoprefixer';
import postcssUrl from 'postcss-url';
import pkg from './package.json' assert { type: 'json' };
import {fileURLToPath} from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const { dependencies = {}, peerDependencies = {} } = pkg;
const externals = [...Object.keys(dependencies), ...Object.keys(peerDependencies)];
const src = path.resolve(__dirname, 'src');
const input = path.resolve(src, 'index.ts');
const assets = path.resolve(src, 'assets');
const dest = path.resolve(__dirname, 'dist');
export default [
{
input,
external: (id) => externals.some((dep) => id === dep || id.startsWith(`${dep}/`)),
plugins: [
typescript({ tsconfig: './tsconfig.json' }),
commonjs(),
json(),
resolve({ browser: true }),
babel({
extensions: ['.ts', '.js', '.tsx', '.jsx'],
}),
image(),
postcss({
plugins: [
autoprefixer,
postcssUrl({
url: 'inline',
basePath: assets,
}),
],
}),
copy({
targets: [
{ src: 'src/**/_*.scss.d.ts', dest },
{ src: 'src/**/_*.scss', dest },
],
}),
],
output: [
{
file: pkg.main,
format: 'cjs',
},
{ name: pkg.name, file: pkg.module, format: 'es' },
{
name: pkg.name,
file: pkg.browser,
format: 'umd',
globals: {
react: 'React',
},
},
{
name: pkg.name,
file: pkg['browser:min'],
format: 'umd',
globals: {
react: 'React',
},
plugins: [terser()],
},
],
},
];
Does someone has any idea why it is doing so ?
I tried to delete node_modules and package-lock.json and reinstall both on my library and front app but I still have the same error.
I tried to import from 'chart.js/auto' as mentioned in the documentation but it throws :
Module not found: Error: Package path ./auto is not exported from package node_modules/chart.js
I looked at node_modules/chart.js/package.json file and there is a well defined set of exports there. But as it came with the upgrade and no other library has ever throw me this error I guess it comes from the upgrade.
Found the bug. As I thought it is a problem with the library itself. It cannot be required since the conditional subpath is missing from the package.json file. Nothing I can do. I'll downgrade untill the push a fix.
I have a rollup library that is trying to use Antd react components. Without external component libraries, everything works fine. If I add the component library (material ui complains of a similar issue), it complains about trying to import variables that are not exported while importing the component library.
rollup.config.js:
export default [
{
input: 'src/index.ts',
output: [
{
file: packageJson.main,
format: 'cjs',
sourcemap: true,
globals: {
react: 'React',
'react-dom': 'ReactDOM',
},
plugins: [visualizer({ open: useVisualizer })],
},
{
file: packageJson.module,
format: 'esm',
sourcemap: true,
globals: {
react: 'React',
'react-dom': 'ReactDOM',
},
},
],
external: ['react', 'react-dom'],
plugins: [
resolve({
preferBuiltins: true
}),
commonjs({
transformMixedEsModules: true,
requireReturnsDefault: 'auto',
esmExternals: true,
// dynamicRequireTargets: ['node_modules/antd/es/**/*.js']
}),
typescript({ tsconfig: './tsconfig.json' }),
folder(),
postcss({
plugins: [],
}),
eslint(),
terser(),
],
},
{
input: './src/index.ts',
output: [{ file: 'dist/index.d.ts', format: 'esm' }],
plugins: [dts()],
external: [/\.css$/],
},
];
Error message:
[!] Error: 'Group' is not exported by node_modules/antd/es/radio/radio.js, imported by node_modules/antd/es/calendar/Header.js
However, when we look at the exports from radio.js, 'Group' is clearly exported from radio/index.js from within the radio directory:
import Group from './group';
import InternalRadio from './radio';
import Button from './radioButton';
export { Button, Group };
var Radio = InternalRadio;
Radio.Button = Button;
Radio.Group = Group;
Radio.__ANT_RADIO = true;
export default Radio;
Header.js imports this like so: import { Button, Group } from '../radio';, so the import SHOULD be going to radio/index.js, however, it appears it is actually going to radio/radio.js instead. No amount of rollup configuration has made this change so far. Any ideas how to get this to resolve to index.js instead of radio.js?
Turns out the normal node-resolve plugin does not resolve "local" imports (i.e. file system paths instead of package paths). The solution here is to also use rollup-plugin-local-resolve, which does resolve these paths.
I want to configure rollup to take a bunch of files on input & produce a bunch of files in dist that share some common code between them.
Here's the rollup config I use:
import path from 'path';
import pathsTransformer from 'ts-transform-paths';
import alias from '#rollup/plugin-alias';
import commonjs from '#rollup/plugin-commonjs';
import { nodeResolve } from '#rollup/plugin-node-resolve';
import typescript from 'rollup-plugin-typescript2';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
const plugins = [
peerDepsExternal(),
alias({
entries: [
{ find: '#', replacement: path.join(__dirname, '/src') },
{ find: '$root', replacement: __dirname },
],
}),
nodeResolve(),
typescript({
transformers: [() => pathsTransformer()],
}),
commonjs({
extensions: ['.js', '.ts'],
}),
];
export default [
{
input: './src/a.ts',
output: {
file: 'dist/a.js',
format: 'esm',
sourcemap: true,
},
plugins,
},
{
input: './src/b.ts',
output: {
file: 'dist/b.js',
format: 'esm',
sourcemap: true,
},
plugins,
},
];
The problem with this set-up is that if a.ts & b.ts both depend on some code, this common code gets bundled into each output file unnecessarily increasing the bundle size.
Since the output.format is esm (so, imports are available in the output), I'd rather expect rollup to split the shared code between the 2 files in a separate chunk & then make both files import that common code (which seems to be the thing rollup does by default anyway).
I assume the problem to be somewhere around nodeResolve or commonjs calls, but, I want my dependencies to be bundled. I just don't want to have them duplicated.
How do I optimize my output? Here's a reproduction to visualize it (dist included).
By returning an array of objects, you specify to rollup that you want to have independent bundles. If you just want to produce multiple files (which was exactly my case) you can just specify input as an object.
import path from 'path';
import pathsTransformer from 'ts-transform-paths';
import alias from '#rollup/plugin-alias';
import commonjs from '#rollup/plugin-commonjs';
import { nodeResolve } from '#rollup/plugin-node-resolve';
import typescript from 'rollup-plugin-typescript2';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
const plugins = [
peerDepsExternal(),
alias({
entries: [
{ find: '#', replacement: path.join(__dirname, '/src') },
{ find: '$root', replacement: __dirname },
],
}),
nodeResolve(),
typescript({
transformers: [() => pathsTransformer()],
}),
commonjs({
extensions: ['.js', '.ts'],
}),
];
export default {
input: {
a: './src/a.ts',
b: './src/b.ts',
},
output: {
dir: 'dist',
format: 'esm',
sourcemap: true,
},
plugins,
};
I'm writing JS library using rollup-starter-lib as base of my JS library
"version": "1.29.0"
It has main.js file & main.css file, There is no html file.
main.js file is all about DOM manipulation, main.css file is necessary in implementation steps, to easily integrate this JS library, rather giving an instruction to user.
I feel like it's .css file not creating due to tree shaking because of css not used in this JS library itself.
Current Distribution
-dist
--my-faceapi-js-lib.cjs.js
--my-faceapi-js-lib.esm.js
--my-faceapi-js-lib.umd.js
Expected Distribution
-dist
--my-faceapi-js-lib.cjs.js
--my-faceapi-js-lib.esm.js
--my-faceapi-js-lib.umd.js
--my-faceapi-js-lib.css
copy main.css file into dist folder not expecting since it's not minifying.
rollup.config.js
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import pkg from './package.json';
//import copy from 'rollup-plugin-copy'
//import postcss from 'rollup-plugin-postcss'
export default [
{
input: 'src/main.js',
output: {
name: 'howLongUntilLunch',
file: pkg.browser,
format: 'umd'
},
plugins: [
resolve(), // so Rollup can find `ms`
commonjs() // so Rollup can convert `ms` to an ES module
]
},{
input: 'src/main.js',
output: [
{ file: pkg.main, format: 'cjs' },
{ file: pkg.module, format: 'es' }
]
}
];
main.js
import * as faceapi from "face-api.js";
...
...
...
import 'main.css';
...
...
Basically there is not usage of main.css within JS library it self. but it's necessary when integrate this library.
You need for that to use the rollup-plugin-postcss plugin (you already have it but it's commented):
// rollup.config.js
import postcss from 'rollup-plugin-postcss'
import path from 'path'
export default {
plugins: [
postcss({
extract: path.resolve('dist/my-faceapi-js-lib.css'),
plugins: []
})
]
}
Issue has been fixed after update rollup version from 1.29.0 to 2.26.3`
(also update relevant packages to rollup lib - not sure about related to fix)
"#rollup/plugin-commonjs": "^15.0.0",
"#rollup/plugin-node-resolve": "^9.0.0",
"rollup": "^2.26.3",
and after adding ['./main.css'], as an external.
{
input: 'src/main.js',
external: ['./main.css'],
output: [
{ file: pkg.main, format: 'cjs' },
{ file: pkg.module, format: 'es' }
]
}
rollup.config.js
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import pkg from './package.json';
import postcss from 'rollup-plugin-postcss'
import path from 'path'
export default [
{
input: 'src/main.js',
output: {
name: 'my-faceapi-js-lib',
file: pkg.browser,
format: 'umd'
},
plugins: [
postcss({
minimize: true,
extensions: ['.css'],
extract: path.resolve('dist/face-auth-rnd.css'),
}),
resolve(), // so Rollup can find `ms`
commonjs() // so Rollup can convert `ms` to an ES module
]
},
{
input: 'src/main.js',
external: ['./main.css'],
output: [
{ file: pkg.main, format: 'cjs' },
{ file: pkg.module, format: 'es' }
]
}
];
This can be fixed by adding an extra export which uses the CSS file as input.
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import pkg from './package.json';
import postcss from 'rollup-plugin-postcss'
export default [
{
input: 'src/main.js',
output: {
name: 'howLongUntilLunch',
file: pkg.browser,
format: 'umd'
},
plugins: [
resolve(),
commonjs()
]
},{
input: 'src/main.css',
output: [
{ file: "dist/main.css" }
],
plugins: [
postcss({
minimize: true,
}),
],
}
];
I'm trying to integrate redux into an existing react application. All of my react code is within jsx files. Now i'm introducing redux and a store.js. during the compilation webpack errors on an exepected token error on store.js
webpack.config.js
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'project/static/public/js');
var APP_DIR = path.resolve(__dirname, 'project/static/public/js/components');
module.exports = {
entry: APP_DIR + '/App.jsx',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
resolve: {
alias: {
'react': path.join(__dirname, 'node_modules', 'react')
}
},
module : {
loaders : [
{
test : /\.jsx/,
include : APP_DIR,
loader : 'babel',
presets : ['es2015']
},
{
test : /\.js/,
include : BUILD_DIR,
exclude : /bundle.js||bundle.js.map||node_modules/,
loader : 'babel',
presets : ['es2015']
}
]
},
watchOptions: {
poll: true
}
};
.babelrc
{
"presets": [
"es2015",
"react"
],
"env": {
"start": {
"presets": [
"react-hmre"
]
}
},
"plugins": [
["transform-es2015-arrow-functions", { "spec": true }],
["transform-class-properties"]
]
}
store.js
import { applyMiddleware, createStore} from 'redux';
import combineReducers from './reducers/index.js'
export default createStore(combineReducers)
error message
ERROR in ./project/static/public/js/store.js
Module parse failed: /home/username/git/project/project/static/public/js/store.js Line 1:
Unexpected token
You may need an appropriate loader to handle this file type.
| import { applyMiddleware, createStore} from 'redux';
| import combineReducers from './reducers/index.js'
|
# ./project/static/public/js/components/App.jsx 15:13-32
These files have gone through multiple iterations in trying to resolve and better understand redux. I think the problem is with my webpack configuration.
Which version of Babel are you using? I guess that you need to use the babel-loader in the webpack rule. This configuration works fines with Babel 7 and Webpack 4.
WEBPACK RULE:
{
test: /\.js$/,
include : BUILD_DIR,
exclude : /bundle.js||bundle.js.map||node_modules/,
use: {
loader: 'babel-loader',
},
},
And .babelrc file example:
{
"presets": [[
"#babel/preset-env", {
"useBuiltIns": "entry"
}],
"#babel/preset-react"],
"plugins": [
"#babel/plugin-proposal-class-properties",
"#babel/plugin-proposal-export-default-from",
"react-hot-loader/babel"
]
}
Please, keep in mind you need to install babel-loader at least version 8.0.0, babel core 7.0.0 and webpack 4.23.
But, I'm pretty sure that the problem is that you need to use the babel-loader plugin in webpack. Visit https://github.com/babel/babel-loader
Best!