Errors in importing a react library created using rollup - reactjs

I am writing a React/Next app. I have created a react accordion-component external to the app. I am using rollup to create a package and importing that package into my app. When I run the app I get the error
./node_modules/#zeilsell-user1/accordion-component/dist/esm/index.js
Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
use clientfunction getDefaultExportFromCjs (x) {
| return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
| }
I do not understand why I am seeing this error. The component is ESM so why the CSJ function? Nexrjs uses webpack, but that should handle csj, I can't find anything about loaders anyway.
I am assuming that the issue is on the component side, so I have included the rollup, tsconfig and package files below. Really appreciate any help that the community can offer me as I have been stuck on this problem for ages.
my rollup.config.mjs
import {nodeResolve} from '#rollup/plugin-node-resolve';
import commonjs from "#rollup/plugin-commonjs";
import typescript from "rollup-plugin-typescript2";
import banner2 from "rollup-plugin-banner2";
import dts from "rollup-plugin-dts";
import packageJson from "./package.json" assert { type: "json" };
export default [
{
input: "src/index.ts",
output: [
{
file: packageJson.module,
format: "esm",
sourcemap: true,
},
],
plugins: [
nodeResolve({extensions: [".js", ".jsx", ".ts", ".tsx", ".json"], }),
commonjs(),
typescript({
tsconfig: "./tsconfig.json",
verbosity: 1,
clean: true,
include: ["*.ts+(|x)", "**/*.ts+(|x)"],
}),
banner2(() => `use client`),
],
},
{
input: "dist/esm/index.d.ts",
output: [{ file: "dist/index.d.ts", format: "esm" }],
plugins: [dts()],
},
];
my tsconfig.json is
{
"compilerOptions": {
"target": "es2016",
"lib": ["es6", "dom", "es2016", "es2017"],
"jsx": "react-jsx",
"module": "ESNext",
"moduleResolution": "node",
"declaration": true,
"sourceMap": true,
"outDir": "dist",
"preserveConstEnums": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true
},
"include": ["src/**/*.ts*"],
"exclude": ["node_modules", "dist"]
}
and the package.json is
{
"name": "#zeilsell-user1/accordion-component",
"type": "module",
"version": "0.0.5",
"description": "This is a simple accordion component to be used with react/next apps",
"author": "...>",
"license": "MIT",
"private": false,
"main": "index.js",
"module": "dist/esm/index.js",
"files": [ "dist" ],
"types": "dist/index.d.ts",
"repository": "https://github.com/zeilsell-user1/accordion-component.git",
"publishConfig": { "registry": "https://npm.pkg.github.com/zeilsell-user1" },
"scripts": {
"rollup": "rollup -c rollup.config.mjs",
"rollup:watch": "rollup -cw",
},
"dependencies": {
},
"devDependencies": {
}
}
I have googled a lot for answers. I added the "type": "module", into the package.json following the suggestion from one site. I also switched to nodeResolve in rollup.config.mjs based on another suggestion. Neither of them changed the outcome.

After a lot of careful combing I realised that if I was specifying "type":"module" then there was no need to include "main": "index.js" as that was specific for cjs.
This solved the issue of cjs being picked up by the app rather than esm. It did result in another issue,below, but that is a 'good' problem as it is correctly picking up esm now!
./node_modules/#zeilsell-user1/accordion-component/dist/esm/index.js
Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
use clientimport { jsxs, Fragment, jsx } from 'react/jsx-runtime';
| import { useState } from 'react';
| import styled from 'styled-components';

Related

Jest can't run test with methods in .tsx file

Usually I only test files that ends with .ts, but in this case I have a file with utility methods that returns a react element. So in this case my file has a .tsx extension and returns some components from material ui and other libraries.
I was getting an error saying SyntaxError: Cannot use import statement outside a module but I solved it by adding "^.+\\.(ts|js)x?$": "ts-jest" to the transform property of my jest.config.js.
But after that I got another error:
● Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
C:\projetos\COM.FLOU.FrontEnd\node_modules\overlayscrollbars\css\OverlayScrollbars.css:19
html.os-html > .os-host {
^
SyntaxError: Unexpected token '.'
jest.config.ts
import { pathsToModuleNameMapper } from "ts-jest/utils";
import { compilerOptions } from "./tsconfig.paths.json";
export default {
coverageDirectory: "coverage/jest",
testEnvironment: "jsdom",
testMatch: ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[tj]s?(x)"],
testPathIgnorePatterns: ["\\\\node_modules\\\\", "<rootDir>/cypress/"],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: "<rootDir>/" }),
transform: {
"^.+\\.jsx?$": "babel-jest",
"^.+\\.(ts|js)x?$": "ts-jest",
".+\\.(css|styl|less|sass|scss)$": "jest-css-modules-transform",
},
};
babel.config.js
// babel.config.js
module.exports = {
presets: [
["#babel/preset-env", { targets: { node: "current" } }],
"#babel/preset-react",
"#babel/preset-typescript",
],
plugins: [
[
"#babel/plugin-transform-runtime",
{
regenerator: true,
},
],
],
};
tsconfig.json
{
"compilerOptions": {
"noImplicitAny": true,
"target": "es5",
"module": "esnext",
"jsx": "react-jsx",
"types": [
"jest"
],
"lib": [
"es6",
"DOM"
],
"outDir": "./dist/",
"rootDir": "./src/",
"sourceMap": true,
"removeComments": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"allowJs": true,
"allowSyntheticDefaultImports": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
},
"extends": "./tsconfig.paths.json",
"include": [
"src/**/*"
],
"exclude": [
"jest.config.ts"
]
}
Am I missing any specific configuration?
I solved it by adding an empty styleMock.ts file and adding it to moduleNameMapper on my jest.config.ts file.
styleMock.ts
export default {};
jest.config.ts
import { pathsToModuleNameMapper } from "ts-jest/utils";
import { compilerOptions } from "./tsconfig.paths.json";
export default {
coverageDirectory: "coverage/jest",
testEnvironment: "jsdom",
testMatch: ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[tj]s?(x)"],
testPathIgnorePatterns: ["\\\\node_modules\\\\", "<rootDir>/cypress/"],
moduleNameMapper: {
...pathsToModuleNameMapper(compilerOptions.paths, { prefix: "<rootDir>/" }),
"\\.(css)$": "<rootDir>/styleMock.ts",
},
transform: {
"^.+\\.(ts|js)x?$": "ts-jest",
},
};

Using jsx-react includes React into the bundle

I'm trying to make React UI component libraries. In my tsconfig, if I set {..., "jsx": "react-jsx"}, I see in the bundle index.esm.js that React code is included.
But if I use the old jsx {"jsx": "react"}, React code is not included in the bundle.
I am using rollup to bundle. This is rollup.config.ts
export default {
input: "./index.ts",
output: [
{
file: pkg.main,
format: "cjs",
},
{
file: pkg.module,
format: "es",
},
],
external: ["react", "react-dom", "#emotion", "#mui/material", "#mui/style"],
plugins: [
resolve(),
external(),
commonjs(),
typescript({
useTsconfigDeclarationDir: true,
}),
terser(),
],
};
This is tsconfig
{
"compilerOptions": {
"declaration": true,
"declarationDir": "lib/types",
"esModuleInterop": true,
"moduleResolution": "Node",
"jsx": "react-jsx",
"resolveJsonModule": true,
"strict": true,
"target": "ESNext"
},
"include": ["./**/*"],
"exclude": ["./**/*.stories.tsx", "./lib", "./node_modules"]
}
How can I use the react-jsx and not include the React code in the bundle. I tried setting sideEffects:false in package.json but it did not work.

Can't import const enums in webpack with babel project

I am working on a react project which was built using create-react-app and later we ejected and modified the webpack config a lot. Right now I am having a hard time importing const enums from external libraries. I don't have control over that external package. It has the const enums defined in its d.ts files.
I have tried with babel-plugin-use-const-enum babel plugin and preset. It doesn't help me either.
My webpack config:
.....
.....
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: [paths.appSrc],
loader: require.resolve("babel-loader"),
options: {
customize: require.resolve("babel-preset-react-app/webpack-overrides"),
plugins: [
[require.resolve("babel-plugin-const-enum"), { transform: "constObject" }],
[require.resolve("#babel/plugin-transform-typescript"), { isTSX: true, optimizeConstEnums: true }],
[require.resolve("#babel/plugin-transform-react-jsx")],
[require.resolve("#babel/plugin-proposal-class-properties"), { loose: true }],
[require.resolve("#babel/plugin-proposal-nullish-coalescing-operator")],
[require.resolve("#babel/plugin-proposal-optional-chaining"), { isTSX: true }],
[require.resolve("#babel/plugin-transform-arrow-functions")],
[require.resolve("#babel/plugin-proposal-private-methods"), { loose: true }],
[
require.resolve("babel-plugin-named-asset-import"),
{
loaderMap: {
svg: {
ReactComponent: "#svgr/webpack?-svgo,+titleProp,+ref![path]",
},
},
},
],
],
presets: ["#babel/preset-env"],
},
},
.....
.....
My tsconfig:
{
"compilerOptions": {
"typeRoots": ["./typings", "node_modules/#types"],
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"noEmit": true,
"jsx": "react",
"downlevelIteration": true
},
"exclude": ["dist/**/*"],
}
The problem is that the build is successful but I am facing the runtime issue with all the const enums import like below
Uncaught TypeError: Cannot read properties of undefined (reading '<ConstEnumName>').
Package versions:
"#babel/core": "^7.11.6",
"babel-loader": "^8.1.0",
"typescript": "^3.9.7",
"webpack": "^4.44.2",
According to this thread, where the plugin's creator is involved, babel does not transpile .d.ts files, making it impossible to get enums from there. The only option seems to be migrating your config to use ts-loader and include the .d.ts files that have the enum declarations
tsconfig
{
...
"exclude": ["dist/**/*"],
"include": ["node_modules/[external_library]/**/*.d.ts"],
}

Rollup and typescript bundle is without editor code completion and jump to declaration

Very new to bundling. My team is used to code completion and being able to jump to the type declaration file of a corresponding component using command + click in their editor (VSCode).
However the bundle generated does not come with this behaviour... I don't know how to go form here, or what I am missing. These feature are very important to my team. Any help is appreciated 🙏
Versions
typescript: 3.7.5
rollup: 1.31.0
rollup-plugin-typescript2: 0.26.0
rollup.config.js
import babel from 'rollup-plugin-babel';
import commonjs from '#rollup/plugin-commonjs';
import resolve from '#rollup/plugin-node-resolve';
import typescript from 'rollup-plugin-typescript2';
import svgr from '#svgr/rollup';
import url from '#rollup/plugin-url';
import json from '#rollup/plugin-json';
import external from 'rollup-plugin-peer-deps-external';
import includePaths from 'rollup-plugin-includepaths';
const pkg = require('./package.json');
export default {
cache: false,
input: 'src/index.ts',
output: { file: pkg.module, format: 'esm' },
plugins: [
external({
preferBuiltins: false,
}),
babel({
exclude: /node_modules/,
plugins: ['external-helpers'],
externalHelpers: true,
}),
json(),
resolve(),
svgr({
ref: true,
svgo: false,
}),
typescript({
clean: true,
typescript: require('typescript'),
}),
url(),
includePaths({
paths: ['src'],
}),
commonjs({
namedExports: {
'prop-types': [
'oneOfType',
'func',
'shape',
'any',
'number',
'object',
'bool',
'string',
],
},
}),
],
};
tsconfig.json
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"baseUrl": "src",
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"jsx": "react",
"lib": ["dom", "dom.iterable", "esnext"],
"module": "es6",
"moduleResolution": "node",
"noEmit": true,
"noErrorTruncation": true,
"outDir": "./dist",
"skipLibCheck": true,
"strict": true,
"target": "es5",
"rootDir": "src"
},
"include": ["src"],
"exclude": ["storybook", "dist"]
}
package.json
Relevant bits only 👇
{
"main": "dist/index.js",
"module": "dist/index.js",
"typings": "dist/index.d.ts",
}
Found the issue - it was because I was using absolute paths. Changing import paths to relative imports or using a plugin to convert absolute to relative import paths when building fixes this issue.

Fuse-Box,VSCode,React,Typescript and debugging

I have issue in my VSCode (1.24.0) with Debugger for Chrome extensions(4.5.0) and debugging react application bundling over fuse-box bundler.
tsconfig.json:
{
"compilerOptions": {
"lib": ["es2015", "dom"],
"moduleResolution": "node",
"module": "commonjs",
"jsx": "react",
"outDir": "dist",
"noUnusedLocals": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"sourceMap": true,
"target": "es2015"
},
"include": ["src"]
}
fuse.ts:
import { FuseBox, WebIndexPlugin, CSSPlugin } from "fuse-box";
import { task } from "fuse-box/sparky";
import path from "path";
const isProduction = false;
task("default", async () => {
const fuse = FuseBox.init({
homeDir: path.resolve(__dirname, "src"),
output: "public/$name.js",
target: "browser",
log: true,
sourceMaps: { vendor: false },
tsConfig: "tsconfig.json",
plugins: [
CSSPlugin(),
WebIndexPlugin({
template: "src/index.html",
appendBundles: true
})
]
});
if (!isProduction) {
fuse.dev({ port: 4545 });
}
const bundle = fuse
.bundle("app")
.target("browser")
.instructions("> index.tsx");
if (!isProduction) {
bundle.watch("src**").hmr();
}
await fuse.run();
});
package.json
"ts-node": "^6.1.0",
"typescript": "^2.9.1"
"fuse-box": "^3.2.2",
scripts:
"scripts": {
"start": "node -r ts-node/register ./fuse.ts"
}
My folders structure is:
public/index.html
public/app.js
public/app.js.ap
src/index.html
src/index.tsx
src/Sidebar.tsx
...
./fuse.ts
./tsconfig.json
./package.json
And finally my launch.json:
....
"type": "chrome",
"request": "launch",
"name": "debug-client",
"url": "http://localhost:4545",
"sourceMaps": true,
"webRoot": "${workspaceRoot}",
"sourceMapPathOverrides": {
"/*": "${webRoot}/*"
}
And question is simple, when i run debug from vscode, chrome starts, application starts too, but vscode returns issue breakpoint (breakpoint is grey).
.scripts(debug console)returns right path and debug works in browser.
What am I missing?
Thanks

Resources