14 Typescript (2) with jquery, bootstrap and other module stuff

1. Introduction

  • Modules are rather tedious and difficult to be understood. There are many module types (Commonjs, AMD, UMD, System) as Jurgen Van Moere explains. 
  • Node, however, works well with Commonjs modules but cannot integrate well with other modules (AMD, System..)
  • Webpack comes to the rescue, but it is a bit difficult to use. With the help of some sites like Neoguias and Swashbuckling this task is much more easier.
Our schedule is:
  1. Create the basics
  2. Create a simple web page with html and javascript
  3. Creating a simple module
  4. Importing and using a simple node module (is-what) and @types
  5. Importing and using jquery

1. The basics. Installation

Open VS Code and execute these commands in the terminal window

# create the project folder
mkdir webpack-jq

cd webpack-jq

# create the package.json and ask for project basic info 
npm init -y

# install webpack and cli (opt -D is equivalent to --save-dev )
npm i -D webpack webpack-cli
# create the folder src (sources folder) mkdir src #create the index.js empty file touch src/index.js

# execute webpack (and complains about no mode selected (development or production)
npx webpack 

# install the ts compiler and ts-loader for webpack
npm i --save-dev typescript ts-loader

# create the file tsconfig.json
npx tsc --init


1.1 File webpack.config.js

Create the file webpack.config.js in the project folder with this code

module.exports = {
mode: 'development',
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: {
loader: 'ts-loader'
}
}
]
},

devtool: false,

resolve: {
extensions: ['.ts', '.js']
}
}

the mode may be development or production

By default, the src folder is for the sources, and the main module is main.ts as typescript has been selected.

The devtool:false is for not generating so much "stuff code"

1.2 Other files (tsconfig.json and package.json, yet existing)

The file tsconfig.json file will not be edited at least for now

The file package.json indicates the plugins that have been installed.

{
"name": "webpack-jq",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"ts-loader": "^9.3.0",
"typescript": "^4.6.4",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2"
}
}

the  script "build": "webpack" has been added to the scripts element of this file

2. Hands-on

Create the file src/index.ts

const age: number= 99
console.log(age)

execute 

# build the project using the script "build" from the package.json
npm run build

and the file dist/main.js has been created

if we run in the terminal

node dist/main.js

we get the output

  99

(from the console.log)

Up till now, the project structure is:


3. Using "own" modules

Create the folder src/my-modules 

Create these 2 files inside it (Person.ts and Printer.ts)

Person.ts

export class Person {
private name : string
private age: number

public constructor( name : string, age : number) {
this.name=name
this.age=age

}
public toString() : string {
return `{ Name: ${this.name}, Age: ${this.age} }`;
}
}


Printer.ts

import { Person } from "./Person";

export class Printer {

public static printPerson(person : Person) : void {
console.log(person.toString());
}
public static printPersons(persons : Array<Person>) : void {
for(let entry of persons) {
this.printPerson(entry);
}
}
}

Now edit the src/index.js and copy this code

import { Person } from "./my-modules/Person";
import { Printer } from "./my-modules/Printer";

const persons = new Array<Person>();

persons.push(new Person('John', 30));
persons.push(new Person('Adam', 23));
persons.push(new Person('Kate', 41));

Printer.printPersons(persons);
console.log("--------------------------------")


if we run in the terminal

# build the project using the script "build" from the package.json
npm run build

# execdute the generated file
node dist/main.js

we get the output:

{ Name: John, Age: 30 }
{ Name: Adam, Age: 23 }
{ Name: Kate, Age: 41 }
--------------------------------


4. Using "npm" modules (is-what)

Import the npm module is-what

# import the node module
npm i -D is-what

and it will be installed in the node_modules folder

Now edit the src/index.ts file as follows


import { Person } from "./my-modules/Person";
import { Printer } from "./my-modules/Printer";
import { isString} from "is-what"

const persons = new Array<Person>();

persons.push(new Person('John', 30));
persons.push(new Person('Adam', 23));
persons.push(new Person('Kate', 41));

Printer.printPersons(persons);
console.log("--------------------------------")
const aa="a string"
console.log ("Is \" const aa\" a string?" + isString(aa))
console.log("--------------------------------")


if we run in the terminal

# build the project using the script "build" from the package.json
npm run build

# execdute the generated file
node dist/main.js

we get the output:

{ Name: John, Age: 30 }
{ Name: Adam, Age: 23 }
{ Name: Kate, Age: 41 }
--------------------------------
Is " const aa" a string?true
--------------------------------

5. Using "npm" modules (jquery)

Import the npm module jquery and the @types/jquery

# import the modules from the node repo
npm i -D jquery @types/jquery

and they will be installed in the node_modules folder

Create the file src/index.html. as it is a very simple file you can create it and 

Now edit the src/index.ts file as follows. Take into account that VS Code can generate a html template for you, by typing  htm


and the finally the src/index.html code is:

<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>

<body>
<h1>This is my jquery test....</h1>
<p id="myp">KRAKATOA</p>
<script src="./main.js"></script>
</body>
</html>

The <p> element will be our target !
The <script> element references the src/main.js that has been generated by webpack


And complete the code of src/index.ts as 

import { Person } from "./my-modules/Person";
import { Printer } from "./my-modules/Printer";
import { isString} from "is-what"
import $ from "jquery"

const persons = new Array<Person>();

console.log("------ [1] Testing my own modules -------------------")
persons.push(new Person('John', 30));
persons.push(new Person('Adam', 23));
persons.push(new Person('Kate', 41));

Printer.printPersons(persons);
console.log("------ [2] Testing is-what --------------------------")
const aa="a string"
console.log ("Is \" const aa\" a string?" + isString(aa))
console.log("----- [3] Testing jquery ---------------------------")

// This part is for testing jquery
$("#myp").append(" is an explosive vulcano!")
alert ("JQuery is OK!")


if we run in the terminal

# build the project using the script "build" from the package.json
npm run build

but our html file has not been copied to the dist folder. So copy it manually!!!

and execute the html file (dist/index.html) in the "live server"



we get the output:

6. Copying files from src folder to dist folder

In the previous example, we have copied the src/index,html to the dist folder manually.
this can be avoided. In stackOverflow there are some good answers to this problem:

6.1. Option (1) package.json & webpack.config.js

In the module section of webpack.config.js change to the yellow code.

module.exports = {
mode: process.env.NODE_ENV || 'production',
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: {
loader: 'ts-loader'
}
}
]
},

devtool: false,

resolve: {
extensions: ['.ts', '.js']
}
}


In the scripts section of package.json change to the yellow code


{
"name": "webpack-jq",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "NODE_ENV=production webpack && cp src/index.html dist/index.html",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/jquery": "^3.5.14",
"is-what": "^4.1.7",
"jquery": "^3.6.0",
"ts-loader": "^9.3.0",
"typescript": "^4.6.4",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2"
}
}

if we want to copy also the imgs and icons folders
"build": "NODE_ENV=production webpack && cp src/index.html dist/index.html && cp -r imgs icons dist/",

6.2. Option (2) copy-webpack-plugin

Let's import the copy-webpack-plugin from npm repository

npm i -D copy-webpack-plugin

And follow the instructions from https://webpack.js.org/plugins/copy-webpack-plugin/

7. Using "own" js modules with d.ts file 

Create the folder src/js-modules and insert 2 files in it (myjs.js and myjs.d.ts)


//myjs.js
const thing = 42;

module.exports =  { thing };npm i -D copy-webpack-plugin


//myjs.d.ts
import "./myjs.js";
export declare const thing: number;

Now update src/index.ts as follows

import { Person } from "./my-modules/Person";
import { Printer } from "./my-modules/Printer";
import { isString} from "is-what"
import $ from "jquery"
import { thing} from "./js-modules/myjs"

const persons = new Array<Person>();

console.log("------ [1] Testing my own modules -------------------")
persons.push(new Person('John', 30));
persons.push(new Person('Adam', 23));
persons.push(new Person('Kate', 41));

Printer.printPersons(persons);
console.log("------ [2] Testing is-what --------------------------")
const aa="a string"
console.log ("Is \" const aa\" a string?" + isString(aa))
console.log("----- [3] Testing jquery ---------------------------")

// This part is for testing jquery
$("#myp").append(" is an explosive vulcano!")
alert ("JQuery is OK!")

console.log("----- [4] Testing own js modules -------------------")
console.log(thing)

and with the developers tools, you get this console output

------ [1] Testing my own modules ------------------- main.js:2:90117
{ Name: John, Age: 30 } main.js:2:91022
{ Name: Adam, Age: 23 } main.js:2:91022
{ Name: Kate, Age: 41 } main.js:2:91022
------ [2] Testing is-what -------------------------- main.js:2:90308
Is " const aa" a string?true main.js:2:90377
-----  [3] Testing jquery --------------------------- main.js:2:90444
-----  [4] Testing own js modules ------------------- main.js:2:90594
42 main.js:2:90663
Live reload enabled.

And you can see that "42" has been displayed as expected.

8. Using "bootstrap" module


Import the npm modules bootstrap,  @types/bootstrap, @popperjs/core and also css-loader, style-loader, sass and sass-loader (@popperjs is a dependency pof bootstrap)

# import the modules from the node repo
npm i -D bootstrap @types/bootstrap @popperjs/core css-loader style-loader sass sass-loader

and they will be installed in the node_modules folder

edit the webpack.config.js file as follows:
 

module.exports = {
mode: process.env.NODE_ENV || 'production',
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: {
loader: 'ts-loader'
}
},
{
test: /\.(sc|c)ss$/i,
use: ["style-loader", "css-loader"],
},
]
},

devtool: false,

resolve: {
extensions: ['.ts', '.js']
},
}


Now update src/index.ts as follows

import { Person } from "./my-modules/Person";
import { Printer } from "./my-modules/Printer";
import { isString} from "is-what"
import $ from "jquery"
import { thing} from "./js-modules/myjs"
import { } from "bootstrap"
import 'bootstrap/dist/css/bootstrap.css';


//import './style.css'

const persons = new Array<Person>();

console.log("------ [1] Testing my own modules -------------------")
persons.push(new Person('John', 30));
persons.push(new Person('Adam', 23));
persons.push(new Person('Kate', 41));

Printer.printPersons(persons);
console.log("------ [2] Testing is-what --------------------------")
const aa="a string"
console.log ("Is \" const aa\" a string?" + isString(aa))
console.log("----- [3] Testing jquery ---------------------------")

// This part is for testing jquery
$("#myp").append(" is an explosive vulcano!")
alert ("JQuery is OK!")

console.log("----- [4] Testing own js modules -------------------")
console.log(thing)

console.log("----- [5] Testing bootstrap modules -------------------")
$("#myp").addClass("text-primary")

The output is:



Happy coding









Comentarios

Entradas populares de este blog

05. Resource bundles (i18n)

03. Servlets, Filters and Listeners