I have an external library that is written in the old IIFE style. I have a web component which uses this lib inside. This web component was created with stencil.
Now if I use my web component in some project, I have to include component js file and this external library to the index.html via src file. How can I include this library to the component's compiled code? Is it possible without re-writing it to the es6 module?
This is how my code looks now (in the index.html):
<script src="./myMathLib.js"></script>
<script src="./myWebComponent.js"></script>
I want to have it like this:
<script src="./myWebComponent.js"></script>
This is the code of my component:
import {Component, Prop} from '#stencil/core';
declare var myMathLib: any;
#Component({
tag: 'my-component',
shadow: true
})
export class MyComponent {
#Prop() name: string;
#Prop() age: number;
render() {
return <div>
The age of {this.name} is: {myMathLib.calculate(this.age)}
</div>;
}
}
This is my tsconfig.json:
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"allowUnreachableCode": false,
"declaration": false,
"experimentalDecorators": true,
"lib": [
"dom",
"es2017"
],
"moduleResolution": "node",
"module": "esnext",
"target": "es2017",
"noUnusedLocals": true,
"noUnusedParameters": true,
"jsx": "react",
"jsxFactory": "h"
},
"include": [
"src",
"types/jsx.d.ts"
],
"exclude": [
"node_modules"
]
}
This is my stencil.config.ts:
import { Config } from '#stencil/core';
export const config: Config = {
namespace: 'mycomponent',
outputTargets:[
{ type: 'dist' },
{ type: 'docs' },
{
type: 'www',
serviceWorker: null // disable service workers
}
]
};
Somewhere in the root of your project, there should be a stencil.config.ts file. In there you can specify copy tasks. You can read here how to do this: https://stenciljs.com/docs/config#copy
After you set that up correctly and your ../assets/ folder is being copied to your build folder.
You need to copy your all the external js file inside assets folder.
In your render method you can directly refer js file from /assets/
After some research, I figured out that the best option is to use globalScript property from stencil.config.
I added my library to the assets folder and then added the following line to my stencil.config.ts file:
globalScript:'src/assets/myMathLib.js'
After it, I was able to use myMathLib.calculate(this.age) in the code of the component.
Related
I use electron, typescript, react with preload.
env
"electron": "19.0.6",
"electron-builder": "23.1.0",
"typescript": "4.7.4",
dir
root - public / preload.ts
|____ src / main.tsx
|____ common.d.ts
<common.d.ts>
export interface ItestAPI{
load:() => Promise<void>
}
declare global{
interface Window{
testAPI: ItestAPI
}
}
<main.tsx>
export function Main(){
async function handleClick(){
await window.testAPI.load();
}
return(
...
<btn onClick={handleClick}>
...
)
}
<preload.ts>
I guess preload and main both refer to same window because it runs well.
If so, why preload.ts shows me red line(error) ?
In the tsconfig.json file add the common.d.ts to the included files. It's going to be like the following.
{
"compilerOptions": {
"target": "es2016",
"jsx": "react",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
},
"include": [
"./public/**/*", // <- Here
"./src/**/*",
"./common.d.ts" // <- Here
],
}
This way VSCode parses the common.d.ts type definition file. Also, after the change, it's better to close and open the VSCode again so it re-parses everything or just wait a minute or so until it detects the changes.
I'm using create-react-app in my ReactJS app with TypeScript, and I would like to import a TypeScript/JavaScript module that I created in another project.
The module consists of a file mymodule.js, in which the code looks approximately like this:
var mymodule;
(function (mymodule) {
var MyClass = /** #class */ (function () {
function MyClass() {
}
MyClass.myMethod = function () {
// code
};
return MyClass;
}());
mymodule.MyClass = MyClass;
})(mymodule || (mymodule = {}));
Then there is the type definition file mymodule.d.ts, which looks like this:
declare module mymodule {
class MyClass {
private static myMethod;
}
}
In my create-react-app project, I placed these two files in the folder /src/vendor, and I want to use the module like this:
import { MyClass } from '../vendor/mymodule';
...
However, Visual Studio Code (i.e. the TypeScript compiler) says
File '.../vendor/mymodule.d.ts' is not a module. ts(2306)
When I run the project, the variables from the module (e.g. the class MyClass) are undefined.
This might be the reason for the error: The library is generated using module: "AMD", but create-react-app seems to enforce module: "esnext".
Edit: Here's the tsconfig.json of the create-react-app project:
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"jsx": "react",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true
},
"include": [
"src"
]
}
You can't import the file due to the fact that you are not exporting the module. In order for module loading to work, you should have an export at the bottom of your myModule class file.
export {
mymodule
}
I'm writing a Typescript library with this structure:
and file contents:
restApi.class.ts
import { restApiOptions } from '../models/rest.options.model';
import { StoreMethods } from '../routes/store.methods.class';
import { UserMethods } from '../routes/user.methods.class';
export class RestApi {
public storeRest: StoreMethods;
public userRest: UserMethods;
constructor(private restApiOptions: restApiOptions) {
.....
}
setLanguage(langId: number){
.....
}
}
store.methodds.class.ts
import { Observable } from 'rxjs';
import { restApiOptions } from '../models/rest.options.model';
import { routeMethods } from '../core/routeMethods.interface';
export class StoreMethods implements routeMethods {
constructor(private restApiOptions: restApiOptions) {
.....
}
setLanguage(languageId: number){
......
}
getStore(storeId: number): Observable<any> {
.....
}
}
and public_api.ts
export { RestApi } from './lib/core/restApi.class'
the library is intended to be used as a dependency in an Angular2+ project, so i have a tsconfig file with the next configuration to transpile it and generate definition files
{
"compilerOptions": {
"outDir": "./dist/",
"declaration": true,
"module": "commonjs",
"target": "es5",
"lib": [
"es2017",
"dom",
"es2015",
"es5",
"es6"
]
},
"exclude": [
"node_modules",
]
}
The problem i have is that this library also needs to be used in a plain es5 javascript project in an "old fashioned way", that is, including the javascript library file in a script tag and using it in a way like this:
var myRestApi = new RestApi(options)
I'm using webpack to combine all files into a single bundle.js file but after generating this file and including it in the project I don't have access to the RespApi class.
this is my webpack.config.js
const path = require('path');
module.exports = [{
entry: './src/public_api.ts',
module: {
rules: [{
test: /\.tsx?$/,
use: [{
loader : 'ts-loader',
options:{
configFile : 'tsconfig.json'
}
}],
exclude: /node_modules/
}]
},
resolve: {
extensions: ['.ts', '.js', '.tsx']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dev')
}
}];
is there a way to transpile the library into a single javascript file and accessing the RestApi class from global??
There's an official guide on webpack's site. I recommend you read it.
Here's the cheatsheet. Add two fields to your webpack.config.js.
webpackConfig.output.library = "RestApi"
webpackConfig.output.libraryTarget = "var"
There's a short coming though. Because you export your module as a named module in public_api.js, user can only access it through window.RestApi.RestApi. Without experimenting, I'm not entirely sure how to solve this.
I'm working on a project where the front-end and the back-end reside in the same directory and both use TypeScript.
I am using a shared path to store some interfaces and constants between the two projects.
But, when I try to export a constant from any file in /shared, I get a :
Error: Cannot find module '#shared/test'
server-config.ts:
"compilerOptions": {
"baseUrl": "./src/server/",
"sourceMap": false,
"module": "commonjs",
"moduleResolution": "node",
"target": "ES2017",
"types": ["node"],
"outDir": "./dist/",
"allowJs": true,
"typeRoots": [
"node_modules/#types"
],
"paths": {
"#shared/*": ["../shared/*"]
},
/shared/test.ts:
// If I remove the following line, no compile error, even finds TheTest
export const TEST = 'test';
export class TheTest {
}
import
// << Module not found (only if I import TEST)
import { TEST, TheTest } from '#shared/test';
export function Foo() {
console.log(TEST);
}
I'm trying to import RxJS 5 into a typescript app using System.js as the module type. It's almost there, but when I do
import * as Rx from "path/to/rxjs/Rx";
the Rx object doesn't contain the module contents of Rx directly, but has a property named 'default' that DOES contain the module contents:
Rx.Observable.of(1,2,3) ... //does not work, Rx.Observable is undefined
Rx.default.Observable.of(1,2,3) ... //DOES work, and contains the module contents as expected
My tsconfig looks like this:
{
"compilerOptions": {
"module": "system",
"allowSyntheticDefaultImports" : true,
"allowJs" : true,
"noImplicitAny": true,
"removeComments": false,
"preserveConstEnums": true,
"baseUrl" : "./",
"sourceMap": true,
"target": "es6",
"lib" : ["dom","es6","dom.iterable","scripthost","es2015","es2016"],
"strict": true,
"forceConsistentCasingInFileNames": true,
"outFile" : "./js/out.js"
},
"files": [
"main.ts"
]
}
And my invocation of system.js looks like this:
System.config({
"baseURL" : "/",
packages: {
'../node_modules/rxjs': {
defaultExtension: 'js',
}
}
});
System.import("./js/out.js")
.then(() => {
console.log("js loaded");
System.import("main");
})
.catch((err)=> {
console.error("Error: " + err);
});
I suspect that this is a configuration variable I need to pass to system.js, but the documentation on cross-module system imports isn't the most helpful to a newbie. I've already tried setting the package type of ../node_modules/rxjs to 'cjs' and it has the same result.
As an aside: 5 different module systems (AT LEAST!) for Javascript is sorta crazy. And I thought the Java Jigsaw brouhaha was bad.
You are importing all exports of path/to/rxjs/Rx in to a new object, Rx.
import * as Rx from "path/to/rxjs/Rx";
To instead import the module's default export, use this:
import Rx from "path/to/rxjs/Rx";