I have a React + Webpack project that is meant to take react modules from a different repo and then bundle them up in a specific way to become web components. I have my modules imported in my package json:
"react-modules": "git+ssh://git@github.com:my-repo#tag,
and use them in my web components project like normal
import { SomeModule } from "react-modules"
However, even when importing a small module, my entire project goes berserk. It analyzes all of react-modules
and fails on every single typescript error inside, including those commented out. I have added the suggested tsconfigs:
"include": ["./src/**/*"],
"exclude": ["node_modules/*", "dist"],
"compilerOptions": {
"baseUrl": ".",
"outDir": "./dist/",
"noImplicitAny": true,
"module": "es6",
"target": "es6",
"jsx": "react",
"allowJs": true,
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"sourceMap": true,
"lib": ["ESNext", "dom"],
"noEmit": true,
"skipLibCheck": true,
"isolatedModules": true,
"esModuleInterop": true,
"noEmitHelpers": true,
"importHelpers": true,
"downlevelIteration": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
}
}
But to not avail.
I expect to be able to import modules without breaking on every single typescript error of the imported module
The package.json of react-modules
:
{
"name": "react-modules",
"version": "0.0.2",
"description": "React modules",
"main": "src/index.ts",
"license": "UNLICENSED",
"peerDependencies": {},
"dependencies": {
"@apollo/client": "^3.7.15",
"@material-ui/core": "^4.11.4",
"@pdftron/webviewer": "8.1.0",
"@rematch/select": "^2.0.5",
"@sentry/browser": "^7.54.0",
"@sentry/react": "^7.54.0",
"@types/material-ui": "^0.21.8",
"apollo-client": "^2.4.5",
"element-closest": "^3.0.0",
"flow-typed": "^3.3.1",
"global": "^4.4.0",
"graphql": "14.0.2",
"graphql-tag": "^2.12.6",
"highcharts": "6.1.1",
"highcharts-react-official": "1.4.0",
"html-to-image": "^1.9.0",
"i18next": "11.9.0",
"i18next-xhr-backend": "3.0.0",
"lodash": "4.17.10",
"moment": "2.22.2",
"prop-types": "15.6.1",
"rc-slider": "^9.7.1",
"react": "16.14.0",
"react-apollo": "2.1.11",
"react-circular-progressbar": "2.0.3",
"react-content-loader": "^4.3.4",
"react-contenteditable": "^3.3.5",
"react-dom": "16.14.0",
"react-i18next": "8.0.6",
"react-intercom": "^1.0.15",
"react-pdf": "^4.1.0",
"react-redux": "^5.1.1",
"react-responsive": "^6.1.1",
"react-select": "^5.7.3",
"react-swipeable": "4.2.0",
"react-tippy": "https://github.com/HiredScore/react-tippy/tarball/39b3b7d625bc8e07b4cb2352149111aace8f007c",
"react-toastify": "^8.1.0",
"react-tooltip": "^4.2.6",
"react-virtualized": "^9.22.3",
"react-widgets": "^4.4.10",
"recompose": "^0.26.0",
"scroll-into-view": "^1.9.3",
"string-pixel-width": "^1.10.0",
"styled-components": "^5.3.3",
"styled-system": "5.1.5",
"typesync": "^0.8.0"
},
"scripts": {
"start": "NODE_ENV=development webpack --mode=development --watch",
"build": "NODE_ENV=production ./node_modules/.bin/webpack --mode=production",
"storybook": "start-storybook -p 9001 -c .storybook -s ./.storybook/static",
"storybook:build": "yarn build-storybook -s ./.storybook/static",
"storybook:ci": "STORYBOOK_CI=true yarn storybook:build",
"design-system": "yarn storybook:build -o designsystem-static",
"test": "node scripts/test.js --env=jsdom --silent",
"test:debug": "yarn test -u --runInBand --no-cache --ci --silent=False",
"test:visual:build": "yarn storybook:ci > /dev/null 2>&1",
"test:visual:run": "yarn loki test --chromeDockerImage yukinying/chrome-headless-browser:93.0.4535.3 --reactUri file:./storybook-static",
"loki-test-report": "reg-cli ./.loki/current ./.loki/reference ./.loki/difference --extendedErrors --enableAntialias --report ./.loki/report.html --json ./.loki/report.json",
"test:visual:update": "yarn storybook:ci && yarn loki update --chromeDockerImage yukinying/chrome-headless-browser:93.0.4535.3 --reactUri file:./storybook-static",
"test:all": "CI=1 yarn test && yarn test:visual:run",
"test:all:update": "CI=1 yarn test -u && yarn test:visual:update",
"build-all": "yarn build",
"typecheck": "tsc --noEmit",
"lint": "eslint src/ --ext .js,.ts,.tsx",
"wtf": "./node_modules/.bin/rimraf node_modules && rm -f package-lock.json && rm -f yarn.lock && yarn cache clean && yarn",
"test:coverage": "yarn test --watchAll=false --coverage",
"generate": "plop"
},
"devDependencies": {
"@babel/cli": "^7.5.0",
"@babel/core": "^7.5.4",
"@babel/helper-builder-react-jsx-experimental": "^7.12.11",
"@babel/helper-define-map": "^7.15.4",
"@babel/plugin-proposal-class-properties": "^7.5.0",
"@babel/plugin-transform-runtime": "^7.5.0",
"@babel/polyfill": "^7.4.4",
"@babel/preset-env": "^7.5.4",
"@babel/preset-flow": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.16.0",
"@babel/register": "^7.4.4",
"@babel/runtime": "^7.5.4",
"@loki/create-async-callback": "^0.28.0",
"@purtuga/esm-webpack-plugin": "^1.5.0",
"@rematch/core": "^1.1.0",
"@storybook/addon-actions": "^6.3.12",
"@storybook/addon-console": "^1.2.3",
"@storybook/addon-controls": "^6.3.12",
"@storybook/addon-essentials": "^6.3.12",
"@storybook/addon-links": "^6.3.12",
"@storybook/addon-storyshots": "^6.3.12",
"@storybook/addon-storyshots-puppeteer": "^6.3.12",
"@storybook/addon-viewport": "^6.3.12",
"@storybook/addons": "^6.3.12",
"@storybook/cli": "^6.3.12",
"@storybook/react": "^6.3.12",
"@svgr/webpack": "^5.4.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "12.0.0",
"@types/babel__core": "^7.1.18",
"@types/babel__plugin-transform-runtime": "^7.9.2",
"@types/babel__preset-env": "^7.9.2",
"@types/case-sensitive-paths-webpack-plugin": "2.1.2",
"@types/element-closest": "^3.0.0",
"@types/enzyme": "3.10.11",
"@types/enzyme-adapter-react-16": "1.0.6",
"@types/eslint": "^8.4.1",
"@types/eslint-plugin-prettier": "^3.1.0",
"@types/file-loader": "5.0.1",
"@types/html-webpack-plugin": "3.2.6",
"@types/jest-specific-snapshot": "^0.5.5",
"@types/lodash": "4.14.178",
"@types/mini-css-extract-plugin": "^2.5.1",
"@types/mockdate": "3.0.0",
"@types/optimize-css-assets-webpack-plugin": "5.0.1",
"@types/prettier": "^2.4.3",
"@types/prop-types": "15.7.4",
"@types/react": "^18.0.12",
"@types/react-dev-utils": "^9.0.11",
"@types/react-dom": "^18.0.5",
"@types/react-pdf": "^5.7.2",
"@types/react-redux": "^7.1.24",
"@types/react-responsive": "^8.0.5",
"@types/react-test-renderer": "17.0.1",
"@types/react-virtualized": "^9.21.16",
"@types/react-widgets": "^4.4.7",
"@types/recompose": "^0.26.5",
"@types/rimraf": "^3.0.2",
"@types/scroll-into-view": "^1.16.0",
"@types/string-pixel-width": "^1.7.2",
"@types/styled-components": "^5.1.25",
"@types/styled-system": "^5.1.15",
"@types/webpack": "5.28.0",
"@types/webpack-dev-server": "3.11.0",
"@types/webpack-manifest-plugin": "3.0.5",
"@types/workbox-webpack-plugin": "3.6.3",
"@typescript-eslint/eslint-plugin": "^5.6.0",
"@typescript-eslint/parser": "^5.6.0",
"add": "^2.0.6",
"add-npm-scripts": "^1.0.0",
"addon-storyshots-selenium": "0.1.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^24.8.0",
"babel-loader": "8.0.4",
"babel-plugin-import-graphql": "^2.6.2",
"babel-plugin-named-asset-import": "0.3.1",
"babel-plugin-react-generate-property": "1.0.5",
"babel-plugin-require-context-hook": "1.0.0",
"babel-plugin-styled-components": "^1.10.0",
"babel-plugin-transform-dynamic-import": "^2.1.0",
"babel-preset-react-app": "^9.0.0",
"case-sensitive-paths-webpack-plugin": "2.1.2",
"css-loader": "1.0.0",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
"eslint": "^7.32.0",
"eslint-config-airbnb": "17.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-import-resolver-typescript": "^2.5.0",
"eslint-loader": "2.1.1",
"eslint-plugin-flowtype": "3.0.0",
"eslint-plugin-import": "2.14.0",
"eslint-plugin-jest": "21.25.1",
"eslint-plugin-jsx-a11y": "6.1.2",
"eslint-plugin-node": "5.1.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "3.5.0",
"eslint-plugin-react": "7.11.1",
"eslint-webpack-plugin": "^2.5.2",
"expect": "23.1.0",
"file-loader": "2.0.0",
"html-webpack-plugin": "4.0.0-beta.5",
"jest": "^26.0",
"jest-junit": "6.4.0",
"jest-specific-snapshot": "^1.0.0",
"jest-styled-components": "^7.0.8",
"loki": "^0.28.1",
"mini-css-extract-plugin": "^0.4.2",
"mockdate": "2.0.2",
"optimize-css-assets-webpack-plugin": "5.0.1",
"plop": "^3.1.1",
"pnp-webpack-plugin": "1.1.0",
"postcss-flexbugs-fixes": "4.1.0",
"postcss-loader": "3.0.0",
"postcss-preset-env": "^6.6.0",
"postcss-safe-parser": "4.0.2",
"prettier": "^2.4.0",
"react-dev-utils": "5.0.2",
"react-svg-loader": "3.0.3",
"react-test-renderer": "16.4.0",
"reg-cli": "^0.16.1",
"rimraf": "^2.6.3",
"sass-loader": "7.1.0",
"storybook-addon-locale": "^0.3.6",
"style-loader": "0.23.1",
"ts-migrate": "^0.1.26",
"typescript": "^4.5.2",
"url-loader": "1.1.2",
"webpack": "4.44.2",
"webpack-cli": "3.1.2",
"webpack-dev-server": "3.11.0",
"webpack-manifest-plugin": "2.0.4",
"webpack-md5-hash": "0.0.6",
"workbox-webpack-plugin": "3.6.3"
},
"resolutions": {
"enzyme/cheerio": "=1.0.0-rc.3"
},
"loki": {
"requireReference": true,
"chromeDockerWithoutSeccomp": true,
"chromeFlags": "--headless --disable-gpu --hide-scrollbars --no-sandbox",
"chromeSelector": ".wrapper > *, #root > *",
"configurations": {
"chrome.laptop": {
"target": "chrome.docker",
"width": 1366,
"height": 768,
"mobile": false,
"fetchFailIgnore": "/sample-videos/"
}
}
}
}
The structure is basically: src/components/component/component.tsx
, it's redux so there's also: src/blocks/block/index.ts
with it's container, view, component and model.
TLDR; You need to specify
main
andtypes
field in the librariespackage.json
file.
You need to understand how TypeScript changes the workflow for developing Node.js/NPM based applications.
To start with, you are authoring your library react-modules
using TypeScript. When you install it in some other project as a dependency
, either via npm
registry or using the git+ssh://
specified in package.json
of your consuming application, it gets installed inside the node_modules
folder. Anything inside the node_modules
should be JavaScript and not the raw TypeScript source files (unless, you are using Deno or similar TS runtime.)
When you introduce TypeScript in you tech stack, your workflow is roughly this:
TypeScript
.tsc
, it compiles your source code into a JavaScript code. You can put this generated code anywhere. Generally something like a <ROOT>/dist
or <ROOT>/build
folder is used as a convention.tsc
is not enough. You will need a bundler like Webpack to exact CSS into a standalone CSS file. For libraries, the Rollup.js
is a better choice due to various reasons.tsc
generates two files for each source .ts
file - one plain old .js
file that contains no TS code and other is *.d.ts
file which TypeScript compiler uses to understand the shape and types exposed by your library.*.d.ts
are pure definitions files. Their absence has no impact on Node.js or even the bundler like Webpack. It only impact when you run type check using the tsc
.git+ssh://
protocol), you need to generate the dist
folder and make it part of your tag (effectively committing the generated dist
folder).dist
folder to generate the compiled code and your library's barrel file is src/index.ts
, then you need to update your package.json
of the library with following fields:{
"name": "react-modules",
"main": "./dist/index.js",
"types": "./dist/index.d.ts"
}
You may also end up using newer exports
and type
field depending on the requirements and target.
So to summarize, you cannot directly using .ts
file as a package's main
entry file. You need to compile the library's ts
code and use the generated code and publish the NPM module or git tag with that generated code.