DEV Community

Masui Masanori
Masui Masanori

Posted on

[TypeScript] Try esbuild

Intro

This time, I will try esbuild to bundle my client-side TypeScript files.
Because I have used Webpack to bundle files, and I will replace them.

Base project

Index.cshtml

<div> <div id="message_div"></div> </div> <script src="/js/index.page.js"></script> <script>Page.init("hello");</script> 
Enter fullscreen mode Exit fullscreen mode

index.page.ts

import { IndexView } from "./index.view"; let view: IndexView; export function init(message: string) { view = new IndexView(); view.updateMessage(message); } 
Enter fullscreen mode Exit fullscreen mode

index.view.ts

export class IndexView { private messageDiv: HTMLElement; public constructor() { this.messageDiv = document.getElementById("message_div") as HTMLElement; } public updateMessage(message: string): void { this.messageDiv.textContent = message; } } 
Enter fullscreen mode Exit fullscreen mode

Bundling files

I can bundle the TypeScript files by command.
(On Windows, I have to change execution policy to run PowerShell scripts first)

./node_modules/.bin/esbuild ./ts/index.page.ts --bundle --outfile=./wwwroot/js/index.page.js 
Enter fullscreen mode Exit fullscreen mode

I also can execute it as a JavaScript file.

indexbuild.mjs

import * as esbuild from 'esbuild'; await esbuild.build({ entryPoints: ['ts/index.page.ts'], bundle: true, minify: false, outfile: 'wwwroot/js/index.page.js', }); 
Enter fullscreen mode Exit fullscreen mode

I can execute this by Node.js.

node ./esbuilds/indexbuild.mjs 
Enter fullscreen mode Exit fullscreen mode

Calling functions from outside of TypeScript

After bundling the files, I will get an exception because "Page is not defined".
The bundled file like below.

index.page.js

"use strict"; (() => { // ts/index.view.ts var IndexView = class { constructor() { this.messageDiv = document.getElementById("message_div"); } updateMessage(message) { this.messageDiv.textContent = message; } }; // ts/index.page.ts var view; function init(message) { view = new IndexView(); view.updateMessage(message); } })(); 
Enter fullscreen mode Exit fullscreen mode

To call the function from outside of the TypeScript, I should declare them as global.

index.page.ts

... (window as any).init = (message: string) => { view = new IndexView(); view.updateMessage(message); } 
Enter fullscreen mode Exit fullscreen mode

Index.cshtml

... <script>init("hello");</script> 
Enter fullscreen mode Exit fullscreen mode

Add type declaration

To remove "as any", I will add type declaration files.

global.d.ts

declare global { interface Window { Page: IndexPageApi, }; } export interface IndexPageApi { init: (message: string) => void, } 
Enter fullscreen mode Exit fullscreen mode

tsconfig.json

{ "compilerOptions": { /* Language and Environment */ "target": "es2016", /* Modules */ "module": "commonjs", "baseUrl": "./", "paths": { "*":["*", "./ts/types/*"] }, /* Emit */ "noEmit": true, /* Interop Constraints */ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, /* Type Checking */ "strict": true, "noImplicitAny": true, "strictNullChecks": true, "strictFunctionTypes": true, "strictBindCallApply": true, "strictPropertyInitialization": true, "noImplicitThis": true, "useUnknownInCatchVariables": true, "alwaysStrict": true, "noUnusedLocals": true, "noUnusedParameters": true, "exactOptionalPropertyTypes": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "noUncheckedIndexedAccess": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "allowUnusedLabels": true, "allowUnreachableCode": true, /* Completeness */ "skipLibCheck": true } } 
Enter fullscreen mode Exit fullscreen mode

index.page.ts

... window.Page = { init(message: string) { view = new IndexView(); view.updateMessage(message); } } 
Enter fullscreen mode Exit fullscreen mode

Index.cshtml

... <script>Page.init("hello");</script> 
Enter fullscreen mode Exit fullscreen mode

Resources

Top comments (0)