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

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.

Related

How to import packages with # in React?

I am building an npm package.
When a user is using my package, I wish to for them to import the packages with the "#" like this:
import { Package } from "#initial/package"
I added this to my tsconfig.json:
"baseUrl": ".",
"paths": {
"#": ["src"],
"#/*": ["src/*"],
"#initial": ["src/components"]
}
but when I do an import:
import { Package } from "#initial/package";
It's throwing this error: Cannot find module '#initial' or its corresponding type declarations.
I have my src and tsconfig.json in the root.
You can do that by changing the name for the project to start with # in npm to can use it directly without aliases or any external library.
For example:
in packeage.json: "name": "#initial/package" and this is must be reflect to npm package:
for example:
https://www.npmjs.com/package/#initial/package
Note: You can use phantomChildren if you need to keep your module as is but you need to separate a specific package to build your own dependency: for example:
"_phantomChildren": {
"#initial/package": "....",
},

cant get cypress to work with typescript using CRA

I am trying to get typescript to work with cypress in a react app I created using create-react-app. I followed all the information in this article, but when I try to run a test file, I get the following error.
Conflicting definitions for 'react' found at....
I am using CRA v3 as the article suggests.
This is what I have in my tsconfig.json in my cypress folder.
{
"extends": "../tsconfig.json",
"include": [
"../node_modules/cypress",
"*/*.ts"
],
"compilerOptions": {
"noEmit": false
}
}

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

Protractor with typescript cannot find module 'protractor' after successfully resolved

This problem is killing me. Please help.
I have following file structure:
node_modules
protractor
typescript
package.json
register-popup.ts
The content of package.json
{
"name": "typescriptProba",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"protractor": "^4.0.11",
"typescript": "^2.0.10"
}
}
The content of register-popup.ts:
import { ElementFinder, element, by } from "protractor";
export class RegisterPopup {
public registerWithFacebookButton: ElementFinder = element(by.css('li.facebook a'));
public registerWithGoogleButton: ElementFinder = element(by.css('li.google a'));
public registerWithEmailButton: ElementFinder = element(by.css('li.email a'));
public registerWithMobileButton: ElementFinder = element(by.css('li.natel a'));
constructor () {}
openPopup() {
element(by.css('.account.user')).click();
element(by.id('openRegister')).click();
}
openRegisterByEmailPopup() {
this.registerWithEmailButton.click();
}
openRegisterByPhonePopup() {
this.registerWithMobileButton.click();
}
}
For compiling ts file to js file I am using following command:
./node_modules/typescript/bin/tsc "./register-popup.ts" --module commonjs --noResolve --traceResolution
After executing command I have following error:
error TS2307: Cannot find module 'protractor'.
But my module trace resolution is like this:
======== Resolving module 'protractor' from '/Users/predraglazarevic/www/typescriptProba/register-popup.ts'. ========
Module resolution kind is not specified, using 'NodeJs'.
Loading module 'protractor' from 'node_modules' folder.
File '/Users/predraglazarevic/www/typescriptProba/node_modules/protractor.ts' does not exist.
File '/Users/predraglazarevic/www/typescriptProba/node_modules/protractor.tsx' does not exist.
File '/Users/predraglazarevic/www/typescriptProba/node_modules/protractor.d.ts' does not exist.
Found 'package.json' at '/Users/predraglazarevic/www/typescriptProba/node_modules/protractor/package.json'.
'package.json' has 'typings' field 'built/index.d.ts' that references '/Users/predraglazarevic/www/typescriptProba/node_modules/protractor/built/index.d.ts'.
File '/Users/predraglazarevic/www/typescriptProba/node_modules/protractor/built/index.d.ts' exist - use it as a name resolution result.
Resolving real path for '/Users/predraglazarevic/www/typescriptProba/node_modules/protractor/built/index.d.ts', result '/Users/predraglazarevic/www/typescriptProba/node_modules/protractor/built/index.d.ts'
======== Module name 'protractor' was successfully resolved to '/Users/predraglazarevic/www/typescriptProba/node_modules/protractor/built/index.d.ts'. ========
So I have
Module name 'protractor' was successfully resolved
but still have error
error TS2307: Cannot find module 'protractor'.
Why?
ANSWER
When I omit --noResolve flag it is working. So command should be
./node_modules/typescript/bin/tsc "./register-popup.ts" --module commonjs
I had to set the moduleResolution setting to node in my tsconfig.json file.
"moduleResolution": "node"
After that, I was able to import browser, etc... from protractor.
import { browser } from 'protractor'
First you need to check your tsconfig.json, you see the typeRoots
{
"compileOnSave": false,
"compilerOptions": {
"declaration": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [
"es2016"
],
"module": "commonjs",
"moduleResolution": "node",
"outDir": "path/to/transpiled/files",
"sourceMap": true,
"target": "es6",
"typeRoots": [
"node_modules/#types"
]
}
}
If you have any additional DefinitelyTyped modules, they will be picked up by the typeRoots directory in the local path: node_modules/#types.
Try running:
yarn install && yarn webpack:build
that should download all missing modules and rebuild the UI.
You didn't install protractor module/library in your local. So,
Run this command : npm install --save protractor. If it won't work.
Try this :
Open VSCode and click View -> Terminal
Navigate to the folder in which you want to install the protractor.
Install the Protractor using below command.
npm install protractor -g
4.Restart VSCode. It will add protractor.conf.js file in your local.

Use typings in vscode without reference path for each d.ts

I have TypeScript and Typings working in vs2015 with the Web Analyzer plugin. I've resolved all vs2015 errors. Now I am trying to set it up in vscode. I've setup a gulp task and vscode reports:
error TS2304: Cannot find name 'angular'
I can resolve it with the following line, but is there a simpler way than listing out each file individually? I.e., vs2015 compiles the TypeScript without issue and knows how to use the Typings files.
/// <reference path="../typings/browser/ambient/angular/index.d.ts" />
I started with gulp-tsc and also tried gulp-typescript, but both require this.
var tsc = require("gulp-tsc");
var typescript = require("gulp-typescript");
var $ = require("gulp-load-plugins")({ lazy: true });
gulp.task("ts-watcher", function() {
gulp.watch("./app/**/*.ts", ["ts-compile"]);
});
gulp.task("ts-compile", function() {
var tsProject = typescript.createProject('tsconfig.json');
return gulp.src(config.allts) //["./app/**/*.ts"]
.pipe(typescript(tsProject))
.pipe(gulp.dest("dest/"));
});
gulp.task("default", ["ts-watcher"]);
{
"compilerOptions": {
"module": "amd",
"rootDir": "src",
"sourceMap": true,
"target": "es5",
"removeComments": true,
"outFile": "./build/build.js"
},
"compileOnSave": true,
"exclude": [
"node_modules",
"typings/main",
"typings/main.d.ts",
"packages"
]
}
My typings folder is in the same folder as tsconfig.json.
Restarting VSCode did not help.
This is similar to Including d.ts type definition files in VSCode, but I am 1) including more information, 2) using VSCode 1.1.0, and 3) I have a TSconfig, not a JSconfig. Would a jsconfig help?
Add a main.d.ts file in your app folder. (Or the src folder where all your ts file resides) with below content, (check the relative path based upon your project structure)
/// <reference path="../typings/main.d.ts" />
you might have to restart VS code.
Maybe you shouldn't exclude typings/main.d.ts as you seem to do. This file is the entry point that includes all registered type defs and hence also angular.
A tsconfig (or jsconfig) in your workspace root is required for vscode to automatically pick up type definitions from typings directory in your workspace root.
In the following example only browser .d.ts-files are used.
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"sourceMap": true
},
"exclude": [
"typings/main.d.ts",
"typings/main",
"node_modules"
]
}
To install additional typings you can use the following typings command
typings install --ambient jquery --save
or use one of the following vscode extensions:
typings-installer
typings-autoinstaller

Resources