## Getting Started * Install Dependencies ``` npm init npm install --save-dev ts-node typescript tslib express @types/express ``` ## Create your web server * Create `server.ts` in root folder of your app. ```typescript import * as express from 'express'; import * as http from 'http'; import * as path from 'path'; import { AddressInfo } from 'net'; const app = express(); const PORT = 3000; const HOST_NAME = `localhost`; const PUBLIC_FOLDER = 'public'; app.use(`/${PUBLIC_FOLDER}`, express.static(path.resolve(PUBLIC_FOLDER))); app.all('/*', function(req: express.Request, res: express.Response) { res.sendFile('index.html', { root: path.resolve(PUBLIC_FOLDER) }) }) const server = http.createServer(app); server.listen(PORT, HOST_NAME) .on('listening', function() { const { port, address } = server.address() as AddressInfo; console.log(`Express server started on port ${port} at ${address}.`); }) ``` * Create `public` folder * Create `public/index.html` ```html TypeScript Web Component

Hello World.

``` * Create scripts in package.json ```json "scripts": { "serve": "ts-node -O '{ \"module\": \"commonjs\" }' server.ts" } ``` * Run your server ``` npm run serve ``` * Browse your application ``` http://localhost:3000 ``` ## Create Web Components * Create `src` folder * Create `src/hello-world.ts` * "Hello World" Custom Elements ```typescript class HelloWorld extends HTMLElement { connectedCallback() { this.innerHTML = `

Hello World.

` } } customElements.define('hello-world', HelloWorld); ``` * Update `public/index.html` file ```html TypeScript Web Component ``` ## Setup Build tools using Rollup * Add build dependencies ``` npm install --save-dev rollup rollup-plugin-typescript2 rollup-plugin-node-resolve ``` * Create `build.ts` ```typescript import * as path from 'path'; import { rollup } from 'rollup'; const typescript2 = require('rollup-plugin-typescript2'); const resolve = require('rollup-plugin-node-resolve'); const ENTRY_FILE = `src/hello-world.ts`; const rollupConfig = { inputOptions: { treeshake: true, input: ENTRY_FILE, external: [], plugins: [ typescript2({ check: false, cacheRoot: path.join(path.resolve(), 'node_modules/.tmp/.rts2_cache'), useTsconfigDeclarationDir: true }), resolve() ], onwarn (warning) { if (warning.code === 'THIS_IS_UNDEFINED') { return; } console.log("Rollup warning: ", warning.message); } }, outputOptions: { sourcemap: true, exports: 'named', file: 'public/bundle.js', name: 'hello-world', format: 'es' } } function rollupBuild({ inputOptions, outputOptions }): Promise { return rollup(inputOptions).then(bundle => bundle.write(outputOptions)); } rollupBuild(rollupConfig); ``` * Add scripts to your package.json ```json "scripts": { ... "build": "ts-node -O '{ \"module\": \"commonjs\" }' build.ts" } ``` * Build & Run your application ``` npm run build && npm run serve ``` * Browse your app ``` http://localhost:3000 ``` * Expected error when running the application * In the browser (chrome) open the DevTools (right click the browser then Inspect) * Go to console tab of the browser * Check the error (in red color) ``` bundle.js:17 Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function. at new HelloWorld (bundle.js:17) at bundle.js:24 ``` * Cause of the error. ``` This error means, that you need a polyfill for browser that do support (!) Custom Elements. That sounds a bit strange, but Custom Elements are defined for EcmaScript 2015+ (bases upon classes) and for supporting older browser, we normally compile down to EcmaScript 5 today. The output of your javascript is in es5 format. ``` * How to resolve or fix? * Install custom-elements polyfill. ``` npm i @webcomponents/custom-elements ``` * In your `server.ts` file add `node_modules` folder as one of your static folders ```typescript app.use(`/node_modules`, express.static(path.resolve('node_modules'))); ``` * Add polyfill as script tag in your `public/index.html` ```html ``` * Run your application ``` npm run serve ``` * Browse your app ``` http://localhost:3000 ```