The js file builded by Rollup can't give the right order - javascript

I create a typescript project and use Rollup to build it, but error:
and then I find this bug in the builded file carefully, and discover the class Text has defined before class Carobj
var newcar = (function (exports){
// ......
class Text extends Carobj {
// ......
}
class Carobj {
// ......
}
})({})
So how to make class Carobj in front of Text when use Rollup to build project?
I wanna Rollup can use right order to build codes.

You have a circular dependency between the module exporting CarObj and re-export Text (index.ts) and the module importing CarObj and exporting Text (text.ts).
When you attempt to import anything from index.ts (like your entrypoint does) - it doesn't matter whether that's CarObj or Text or nothing - then it will first load index.ts, then load its dependencies, including text.ts, which in turn loads its dependencies that were not already loaded. After all variables are declared and imports/exports are set up, when all of text.ts' dependencies are met - again excluding index.ts which is already in the process of being imported - it is executed, attempting to initialise the class Text, and runs into an error because the CarObj it attempts to extend is still in the temporal dead zone. If it had finished, the index.ts module could have been executed after all its dependencies were met, and so on, back until the entry point.
So this is not a problem of rollup, it just bundles the code in the same order, with the same scopes, as it would have been executed with individual modules. Which leads to the same exception.
The fix is simple: put the class CarObj into a separate module, and import only that in text.ts, not the index.ts that imports text.ts.
// index.ts
export { CarObj } from "./lib/obj";
export { Text } from "./lib/text";
// lib/obj.ts
export class CarObj {
…
}
// lib/text.ts
import { CarObj } from "./obj";
// ^^^^^^^ - not "../index"!
export class Text extends CarObj {
…
}

Related

When is TypeScript top-level non-export code executed?

I am currently confused on when code in a file is actually executed an when it is not. If I have a file1.ts file like the following:
export interface myInterface {}
export function myFunction() {}
export const myConst: {}
// ... and more exports
// top-level non-exported code
if (condition) {
myConst = ...
}
And a file2.ts containing one the following:
import { myInterface } from "./file1.ts"
import * from "./file1.ts"
import * as file1 from "./file1.ts"
import "./file1.ts"
How does the the behaviour differ? When is the top-level code that wasn't exported in file1.ts executed and when is it not executed? Is it executed even when only a specific export is imported (see first variant)?
This is making me crazy right now and I didn't find anything about it on the TypeScript handbook page for modules.
Multiple conditions determine if TypeScript module gets included in final, transpiled JavaScript files, or not:
Kind of usage of imported variables in the your own code.
Type of imported variables (class, interface, etc).
Since TypeScript 2.8 compiler settings importsNotUsedAsValues to control the behavior.
Since TypeScript 2.8 there is also new syntax import type and export type for modules that are explicitly excluded from final, compiled JavaScript files.
Check following section in the TypeScript 2.8 release notes for more details:
Type-Only Imports and Export

TypeScript declarations for JavaScript module

I recently started using a Node library called bpmn-js (npmjs.com).
It is written in JavaScript, and I'd like to have typings. Thus, I've began reading about d.ts files.
I created this folder structure
webapp
#types
bpmn-js
index.d.ts
With a simple content
declare module 'bpmn-js' {
export class BpmnJS {
constructor();
}
}
But this doesn't seem to work.
"Before" typings, I was able to import the object I needed using
import BpmnJS from 'bpmn-js';
And I was able to instantiate it using
new BpmnJS();
How can I get the typings file to be recognized?
I'm using WebStorm 2019.1.*.
Pretty simple, I was missing export default, or better, the default part.
declare module 'bpmn-js' {
export default class BpmnJS {
constructor(param?: { container: string });
...
}
}
Now this works too
import BpmnJS from 'bpmn-js';

Typescript 2: Custom Type definition in node_modules

Let's say I publish a custom library called my-library. This library will be of the structure
node_modules/
my-library/
lib/
index.js
src/
...
typings/
index.d.ts
package.json
Say now I export default something called Application from the index.js, so you use it by import Application from 'my-library';
Now, in my index.d.ts I want to declare its typing:
export = Application;
export as namespace Application;
declare namespace Application {
function foo(arg1: string): object;
}
I know expect this to return an error but it does not:
import Application from 'my-library';
Application.foo(123)[0].blahblah;
Not only is the argument wrong, but so is the use of the return value. I don't know how I am supposed to add my type definitions so that the above works.
You can look here to see where Typescript looks for definitions.
What you probably want is to add a types in your package.json to point to a custom definition file.
{
"types": "typings/index.d.ts",
}

How to disable Tree shaking in rollupjs

I am trying to bundle together several javascript files using RollUp.js but when I do, the classes that aren't used get removed. This process is called tree shaking and I want to disable it.
I have found this but it doesn't seem to have any effect.
// rollup.config.js
let configuration = {
output: {
format: 'es',
},
name: 'namename',
input: './main.js',
treeshake: false, // <-- disabling tree shaking?
};
export default configuration;
I added treeshake: false to the configuration, but it doesn't seem to have any effect. Is this supposed to be placed somewhere else?
Here are the files I am trying to roll up.
// Base.js
export default class Base {
aMethod() {
return "Hello";
}
}
// main.js
import Base from './Base.js';
So with this set up, I call rollup --config and it produces something empty. So clearly, tree shaking is happening and it is removing the Base class even though I imported it.
So far the only workaround I've found is to actually create an instance of the class, which is undesirable.
// main.js
import Base from './Base.js';
export default function () {
{
new Base();
}
}
My goal is to use the bundled javascript file with JSContext. It will take in the javascript as a string and then from there, I'd invoke methods as needed.
// suppose rollup.js produces a file called "product.js"
let s = String(contentsOfFile: "path/to/product.js")
let context = JSContext()!
context.evaluateScript(s)
context.evaluateScript("var b = new Base()")
context.evaluateScript("b.aMethod()")
But because of the tree shaking the Base class never gets placed in product.js
Is there a way to disable tree shaking?
I've included a sample project for this.
Your entry file — main.js — needs to export any classes or other values that need to be accessible to the outside world:
// main.js
import Base from './Base.js';
import SubB from './SubB.js';
import SubA from './SubA.js';
export { Base, SubA, SubB };

How do we declare import types from NPM library that has no declaration files?

For example, if I have the following in my app,
import Node from 'infamous/motor/Node'
console.log(Node)
that works just fine. But the moment I actually do something with it,
import Node from 'infamous/motor/Node'
console.log(new Node)
then TypeScript will complain because there's no type definition for Node. How do I define the type of Node?
The library has no type declarations of it's own. I tried something like
import MotorNode from 'infamous/motor/Node'
declare class MotorNode {}
console.log(' --- ', new MotorNode)
but I get the error
./src/app.tsx(6,8): error TS2440: Import declaration conflicts with local declaration of 'MotorNode'
When I need to do what you are trying to do, I create an externals.d.ts file in which I put module augmentations for my project and make sure that my tsconfig.json includes it in the compilation.
In your case the augmentation might look something like this:
declare module "infamous/motor/Node" {
class Node {
// Whatever you need here...
}
export default Node;
}
I put it in a separate file because a module augmentation like this has to be global (must be outside any module), and a file that contains a a top-level import or export is a module. (See this comment from a TypeScript contributor.)

Categories

Resources