import/no-unresolved in Bitbucket Pipelines - reactjs

For my React app, my .env file has the following entry:
NODE_PATH=./src
This allows me to use absolute paths when importing packages.
In eslintrc.json, I have this configuration to handle eslint's import/no-unresolved rule:
"settings": { "import/resolver": { "node": { "paths": ["src"] } } },
This set up works in my local environment.
However, when I push my code to Bitbucket, the build fails with this message:
error Unable to resolve path to module 'components/Header/Header' import/no-unresolved
How should I set up Bitbucket Pipelines?

Related

How do I get HMR (Hot Module Replacement) working with a TypeScript React Monorepo in Vite

I've got a React monorepo (build in TypeScript) and I've recently been switching over from Webpack to Vite. However I'm having real difficult in getting HMR working correctly within Vite (I believe because we separately build our packages).
I'm open to options to get this working (although I think I still need to be able to build my packages, for Jest/ESLint performance).
Project Structure
\apps
\main
\packages
\domainA
\foo
\package.json
\build
\src
At the moment each package gets build using tsc "tsc --project tsconfig.lib.json" into the build directory. The package.json defines the following:
"name": "#ig/foo",
"main": "./build/index.js",
"types": "./build/index.d.ts",
"files": [
"/build"
],
I can spin up the main application and if I make a change in /packages/domainA/foo/src/index.ts then it'll build (currently using a watcher) and I get a full page reload.
I'd like to eliminate the page reload and instead use HMR. I don't think changing the entry point to "main": "./src/index.ts" will work for my use-case due to the slowness in the other tools unfortunately. However I'm happy to try and bypass this and re-point Vite to the source files if necessary.
I've tried all sorts of permutations, having looked at a few sample repos. But not managed to get anything working, e.g.
resolve: {
alias: [{
find: '#ig/foo',
replacement: '../packages/domainA/foo/src/index.ts',
},
}
Here is my current Vite config:
import react from '#vitejs/plugin-react';
import fs from 'fs';
import path, { resolve } from 'path';
import { defineConfig } from 'vite';
import mkcert from 'vite-plugin-mkcert';
import svgrPlugin from 'vite-plugin-svgr';
export default defineConfig({
// optimizeDeps: {
// include: ['#infogrid/solution-views-occupancy'],
// },
build: {
outDir: 'build/public',
sourcemap: true,
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
base: resolve(__dirname, 'index_base.html'),
},
}
},
server: {
port: Number(process.env.PORT),
// setting to true allows external ip
host: true,
},
plugins: [
react({ fastRefresh: true }), // Primarily used for HMR
svgrPlugin({ svgrOptions: { icon: true } }), // Turns svgs into react components
mkcert(), // Allows for HTTPS during local development
]
}

StencilJS error with React output target - You may need an additional loader to handle the result of these loaders

I'm creating some basic elements in Stencil for a custom design system. I created some basic components, which work fine on their own as custom elements, but throw errors when used as React components.
I generated the React components via Stencil by includng the #stencil/react-output-target in stencil.config.ts.
reactOutputTarget({
componentCorePackage: '#sr-design-system/simple-stencil-demo',
proxiesFile: './react/src/components/index.ts',
includeImportCustomElements: true
}),
I then uploaded all of the components (custom elements & React) to a private npm package and installed them in a seperate project. The custom elements seem to work fine, but with the React elements I get the following error.
ERROR in ./node_modules/#sr-design-system/simple-stencil-demo/react/src/index.ts 6:12
Module parse failed: Unexpected token (6:12)
File was processed with these loaders:
* ./node_modules/source-map-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
| import { createReactComponent } from './react-component-lib';
|
> import type { JSX } from '#sr-design-system/simple-stencil-demo/';
|
| import { defineCustomElement as defineSrText } from '#sr-design-system/simple-stencil-demo/dist/components/sr-text';
# ./src/App.jsx 7:0-73
# ./src/index.jsx 7:0-24 12:33-36
webpack 5.65.0 compiled with 1 error and 1 warning in 63 ms
I've been stuck on this issue for days now. Any idea what the solution could be?
===tsconfig.json===
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"declaration": true,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"lib": ["dom", "es2017"],
"module": "es2015",
"moduleResolution": "node",
"pretty": true,
"removeComments": false,
"strictPropertyInitialization": false,
"target": "es2017",
"baseUrl": ".",
"paths": {
"#srds/react": ["./react"]
},
"jsx": "react",
"jsxFactory": "h"
},
"include": ["src"]
}
===stencil.config.ts===
import { Config } from '#stencil/core';
import { reactOutputTarget } from '#stencil/react-output-target';
export const config: Config = {
namespace: 'simple-stencil-demo',
bundles: [{ components: ['sr-text'] }, { components: ['text-demo'] }],
outputTargets: [
reactOutputTarget({
componentCorePackage: '#sr-design-system/simple-stencil-demo',
proxiesFile: './react/src/components/index.ts',
includeImportCustomElements: true,
}),
{
type: 'dist',
esmLoaderPath: './loader',
},
{
type: 'dist-custom-elements',
},
{
type: 'docs-readme',
},
{
type: 'www',
serviceWorker: null, // disable service workers
},
],
buildEs5: 'prod',
};
I figured out what the issue. For some reason, the dist folder was not being generated for me every time I ran npm run build.
Sometimes it was generated, other times it wasn't. I believe it was due to some errors in my component code, which failed silently. So now I check for the dist folder every time I build the library.
In my final, working attempt I went with the monorepo approach as advised by the Stencil team in their documentation.
Here are all I took the steps for a basic Stencil library with a React output:
Create a monorepo
Create a Stencil Library
Generate components using npx stencil generate
Update name in package.json to MY_LIBRARY
npm i #stencil/react-output-target
Add the React Wrapper function to stencil.config.ts
react({
componentCorePackage: 'MY_LIBRARY',
proxiesFile: '../MY_REACT_LIBRARY/src/components/stencil-generated/index.ts',
includeDefineCustomElements: true,
}),
Move back to root level of monorepo
Create a React library
git clone https://github.com/ionic-team/stencil-ds-react-template react-components
Update name in package.json to MY_REACT_LIBRARY
Change private to false in package.json
In the Stencil Library
Run npm run build
Check if dist folder contains all subfolders (cjs, collection, components, esm, types, web-components, index.cjs.js, index.js)
Run npm link to generate a global symlink
In the React Library
Run npm link MY_LIBRARY
Run npm i
Run npm run build (Not sure if this step is required as it is not documented, but I did it anyway)
Run npm link
Move back to root level of monorepo
Create a React demo
npx create-react-app MY_REACT_DEMO --template typescript
npm link MY_REACT_LIBRARY
Import a component from the library and use it in App.tsx
npm run start
When I confirmed everything worked fine, I added a basic lerna.jsonconfig for npm package management. Using this config, Lerna will automatically handle symver for our packages.
{
"version": "independent",
"npmClient": "npm",
"command": {
"publish": {
"allowBranch": ["master", "react-generation"],
"ignoreChanges": ["*.md", "build.js", "config.json"],
"message": "(auto) Lerna publish",
"registry": "URL_TO_MY_PACKAGE_REGISTRY"
},
"bootstrap": {
"ignore": "component-*",
"npmClientArgs": ["--no-package-lock"]
}
},
"packages": ["MY_LIBRARY", "MY_REACT_LIBRARY"]
}
After configuring Lerna, I published using the command npx lerna publish, following their publishing wizard.
When it's published the package can be installed in any React project using npm i MY_REACT_LIBRARY and it should work.

React Monorepo yarn workspaces + typescript + absolute imports

I'm having issues setting up an React project with yarn workspaces and typescript.
My folder structure is:
-root
-package.json
-workspaces
-web
-common
and my package.json file is:
{
"name": "my-project-name",
"private": true,
"workspaces": [
"workspaces/web",
"workspaces/common"
],
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]
}
My issue is: when I import files on web from the common project, it works fine if it's a .js file, but fails with TypeError: Object(...) is not a function when using .ts or .tsx files.
Any ideas on what I might be missing?
I recommend adopting the following file hierarchy:
- root
- package.json
- tsconfig.json
- packages
- common
- package.json
- tsconfig.json
- services
- web
- package.json
- tsconfig.json
Everything in the packages folder can be imported. Services are "leaf" projects that you don't want to import in other projects.
With that as a base, your root package.json should be setup like that:
{
"name": "my-project-name",
"private": true,
"workspaces": [
"packages": [
"packages/*",
"services/**/*"
],
],
}
Then, you also need to tell typescript how to resolve the imports.
In the root tsconfig.json, set the following:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#myproject/*": ["packages/*/src"]
},
}
Make sure that every tsconfig extends this base with "extends": "../../tsconfig.json"
Inside web/package.json or any package that needs to import common, define common as a dependency:
{
[...]
"dependencies": {
"#myproject/common": "*",
}
}
Now if your common package.json has a name set to `"#myproject/common", you can import your code inside web with :
import { myUtilFunction } from "#myproject/common";
I would advise you to also use learn with a setup like this.
You will also need to modify a bit your build pipeline, since you're importing files inside /web that are outside the /web folder. For a more complete example, you can check out this repo: https://github.com/NiGhTTraX/ts-monorepo

How to provide `babel-preset-react-app` env variables?

I am working on an App which connects create-react-app with an express server( using server rendering). I am referring this tutorial for it.To render the file from server, the code is
bootstrap.js
require('ignore-styles');
require('babel-register')({
ignore:[/(node-modules)/],
presets:['es2015','react-app']
});
require('./index');
index.js
import express from 'express';
// we'll talk about this in a minute:
import serverRenderer from './middleware/renderer';
const PORT = 3000;
const path = require('path');
// initialize the application and create the routes
const app = express();
const router = express.Router();
// root (/) should always serve our server rendered page
router.use('^/$', serverRenderer);
// other static resources should just be served as they are
router.use(express.static(
path.resolve(__dirname, '..', 'build'),
{ maxAge: '30d' },
));
// tell the app to use the above rules
app.use(router);
// start the app
app.listen(PORT, (error) => {
if (error) {
return console.log('something bad happened', error);
}
console.log("listening on " + PORT + "...");
});
While running the command
node bootstrap.js
I am getting error that
Error: Using babel-preset-react-app requires that you specify NODE_ENV or BABEL_ENV environment variables. Valid values are "development", "test", and "production".
There are a few options here. I will describe the most easy options.
The most easy one is to run your node bootstrap.js like this:
NODE_ENV=production BABEL_ENV=production node bootstrap.js
But that is just too long to remember every time, so you can use package.json scripts.
If you open up your package.json file, you should see a scripts section (if not, see the doc). In that scripts section you can create your own scripts.
I mostly use 2 scripts, one for development and one for production. So in your case something like:
"scripts": {
"start": "NODE_ENV=development BABEL_ENV=development node bootstrap.js",
"serve": "NODE_ENV=production BABEL_ENV=production node bootstrap.js"
}
Now you can run your node app like this:
In development
node run start or node start (because node start is an alias for node run start)
and in production
node run serve (no shorthands here)
If you still think your package.json becomes too large, you can abstract that away to some .js files. And change your scripts accordingly to something like:
"scripts": {
"start": "node scripts/start.js"
"serve": "node scripts/serve.js"
}
In those script files you can define both of those environment variables before running your app.
For solving the next error
0:0 error Parsing error: [BABEL] {some-path}: Using `babel-preset-react-app` requires that you specify `NODE_ENV` or `BABEL_ENV` environment variables. Valid values are "development", "test", and "production". Instead, received: undefined. (While processing: "{project-path}\\node_modules\\babel-preset-react-app\\index.js")
It was useful for me to add
"parser": "#typescript-eslint/parser",
into "eslintConfig" block in the package.json of my React app.
Error: Using babel-preset-react-app requires that you specify NODE_ENV or BABEL_ENV
Answer for CRA(create react app):
#origin post https://github.com/facebook/create-react-app/issues/2377
#Error:
0:0 error Parsing error: [BABEL] {some-path}: Using `babel-preset-react-app` requires
that you specify `NODE_ENV` or `BABEL_ENV` environment variables. Valid values are "development", "test", and "production". Instead, received: undefined. (While processing: "{project-path}\\node_modules\\babel-preset-react-app\\index.js")
#Description:
Problem occured after added .babelrc file to CRA using #rescripts/cli and #rescripts/rescript-use-babel-config.
For fix error you should:
Typescript:
Added "parser": "#typescript-eslint/parser", to your eslint.
Javascript:
Added "parser": "#babel/eslint-parser", to your eslint.
Eslint docs: https://eslint.org/docs/user-guide/configuring/plugins#specifying-parser
Example of typescript eslint config in package.json for CRA:
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest",
"eslint:recommended"
],
"globals": {
"NodeJS": true
},
"parser": "#typescript-eslint/parser",
"overrides": [
{
"files": ["*.ts", "*.tsx"],
"rules": {
"no-undef": "off",
"no-unused-vars": "off",
"#typescript-eslint/no-unused-vars": ["error"]
}
}
],
"rules": {
"no-empty": [
"error",
{
"allowEmptyCatch": true
}
]
}
}

ESLint global vars included via <script> are causing undefined error

My react app is bundled with WebPack and it uses global scripts (e.g. jQuery) that are included via tags and are defined in WebPack externals.
But my ESLint configuration doesn't know about them and i get 'no-unded' error in ESLint.
So how can i tell ESLint that those are not undefined vars, or should i change my WebPack config somehow?
Did you tried adding globals in .eslintric.js config file
module.exports = {
"env": {
"browser": true,
"node": true
},
"globals": {
"SomeVar": true
},
};

Resources