Express and Webpack with Typescript¶
Directory¶
--rets
|--api
|--app
api¶
package.json
{
"name": "api",
"version": "1.0.0",
"description": "",
"main": "server.js",
"type": "module",
"scripts": {
"dev": "nodemon"
},
"dependencies": {
"express": "^4.17.1",
"http-proxy-middleware": "^1.0.4"
},
"devDependencies": {
"@types/express": "^4.17.11",
"@types/node": "^15.3.1",
"nodemon": "^2.0.7",
"ts-node": "^9.1.1",
"typescript": "^4.2.4"
},
"author": "",
"license": "ISC"
}
nodemon.json
{
"verbose":true,
"watch": ["server.ts"],
"ext": "ts,json",
"ignore": ["node_modules"],
"exec": "node --loader ts-node/esm server.ts"
}
npx tsc -init
to get initial tsconfig.json
tsconfig.json
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
"incremental": true, /* Enable incremental compilation */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "es2020", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"strict": true, /* Enable all strict type-checking options. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
}
}
server.ts
import express from 'express';
const port = 3080
const app = express();
app.get('/', (req, res) => {
res.send('Well done!');
})
app.listen(port, () => {
console.log('The application is listening on port '+port);
})
app¶
The npm module react
offer a program create-react-app
that is meant to called from outside the target directory app
. If react
is not installed globally, it is a chicken and egg problem. It is solved here by temporarily installing react
in the parent dir rets
, calling create-react-app
, then deleteing top
's node_modules
and package.json
in rets.
The react
app can serve itself. However, we do it via express. In order for that to work,
a line must be added to the template package.json
:
"proxy": "http://localhost:3080",
Ran npm run eject
and the resulting environment is too complex.
Changing to app2
app2¶
package.json
{
"name": "app2",
"version": "1.0.0",
"main": "src/index.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"serve": "webpack serve --config ./webpack.config.dev.js --progress",
"build": "webpack --config ./webpack.config.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@types/lodash": "^4.14.170",
"ts-loader": "^9.2.1",
"typescript": "^4.2.4",
"webpack": "^5.37.1",
"webpack-cli": "^4.7.0",
"webpack-dev-server": "^3.11.2"
},
"dependencies": {
"lodash": "^4.17.21"
}
}
tsconfig.json
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"jsx": "react",
"allowJs": true,
"moduleResolution": "node",
}
}
webpack.config.dev.js
const path = require('path');
const dist_dir = 'dist-dev'
module.exports = {
mode: 'development',
entry: './src/index.ts',
devServer: {
contentBase: path.join(__dirname, 'dist-dev'),
watchContentBase: true,
proxy: {
'/api': 'http://localhost:3080',
},
},
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, dist_dir),
},
};
webpack.config.dev.js
NOT YET TESTED
src/index.ts
import * as _ from 'lodash';
function component(s:string) {
const element = document.createElement('div');
element.innerHTML = s; //_.join(['Hello', 'foopack'], ' ');
return element;
}
async function main(){
document.body.appendChild(component(_.join(['Hello', 'foopack'],' ')));
const data = await fetch('/api')
.then(response => response.text())
//.then(data => console.log(data));
console.log(data)
document.body.appendChild(component(data));
}
main()
dest-dev/index.html (hard coded for now)
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<script
type="text/javascript"
charset="utf-8"
src="/bundle.js"
></script>
<div>1</div>
<div>2</div>
<div>3</div>
</body>
</html>