Skip to content

Instantly share code, notes, and snippets.

@kva1966
Last active July 26, 2017 05:17
Show Gist options
  • Save kva1966/813c2efa495909da78efcc8eb251c9df to your computer and use it in GitHub Desktop.
Save kva1966/813c2efa495909da78efcc8eb251c9df to your computer and use it in GitHub Desktop.
tsconfig.json and webpack module aliasing Notes
PWD ~/projects/checkouts/my-projects/code-snippets/datastruc-vis
Directory Structure: 'node_modules' excluded, 'dist' is the output/build folder
├── dist
│   ├── bundles
│   │   ├── bundle.js
│   │   └── bundle.js.map
│   └── index.html
├── package.json
├── src
│   ├── bundle-index.js
│   ├── index.html
│   ├── index.ts
│   └── libs
│   ├── common.ts
│   ├── list.ts
│   ├── tree.ts
│   └── util.ts
├── tsconfig.json
├── webpack.config.js
└── yarn.lock
Note this is a simpler project with no tests, otherwise I would stick to
the prat convention of having an 'app' and 'test' source folders, or having
src/app and src/test.
// dependencies were manipulated via:
// yarn add|remove <dep> [--dev]
// e.g. yarn add jquery // prod by default.
// yarn add typescript --dev
// yarn cleanly modifies the correct section of the package.json without breaking other bits.
{
"name": "datastruc-vis",
"version": "1.0.0",
"description": "Data Structures Play and Visualisation",
"scripts": {
"predev": "rimraf dist",
"dev": "webpack --watch",
"prebuild": "rimraf dist",
"build": "webpack",
"serve": "webpack-dev-server --open"
},
"author": "Kamal Advani",
"devDependencies": {
"@types/jquery": "^3.2.9",
"awesome-typescript-loader": "^3.2.1",
"extract-loader": "^0.1.0",
"file-loader": "^0.11.2",
"html-loader": "^0.4.5",
"rimraf": "^2.6.1",
"source-map-loader": "^0.2.1",
"typescript": "^2.4.2",
"uglifyjs-webpack-plugin": "^0.4.6",
"webpack": "^3.3.0",
"webpack-dev-server": "^2.6.1"
},
"dependencies": {
"jquery": "^3.2.1"
}
}
//
// see !!! prefixed comments for interesting bits
//
{
"compilerOptions": {
"allowJs": false,
"target": "es5",
"removeComments": true,
"sourceMap": true,
"noImplicitAny": true,
"preserveConstEnums": true,
// Libraries
"lib": [
"DOM", "DOM.Iterable", "ES6", "ScriptHost"
],
// !!! Module Handling
// !!! Pretty handy to see where things are being searched for.
"traceResolution": true, // DEBUG! Only shows with tsc, not through webpack ts-loader
"module": "commonjs",
"moduleResolution": "node",
// !!! MODULE ALIASING - note that path takes glob pattern matches. I had assumed it was just fixed strings.
// !!! baseUrl must be specified, even to just '.' if it's more convenient, but then adjust the actual paths --
// !!! relative to baseUrl
"baseUrl": "./src",
"paths": {
"app-libs/*": ["libs/*"]
}
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
//
// see !!! prefixed comments for interesting bits
//
const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const { TsConfigPathsPlugin } = require('awesome-typescript-loader');
const config = {
target: 'web',
context: path.resolve(__dirname, 'src'),
entry: {
'bundle': './bundle-index.js'
},
output: {
filename: 'bundles/[name].js',
path: path.resolve(__dirname, 'dist')
},
devtool: "source-map",
devServer: {
contentBase: './dist'
},
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".ts", ".tsx", ".js", ".json"],
// !!! Module resolution aliasing, so we don't use stupid relative paths on importing
// !!! our own code.
// !!! https://webpack.js.org/configuration/resolve/
alias: {
// !!! NOTE:
// !!! Need to set appropriate paths in tsconfig.json as well for TypeScript
// !!! awareness, webpack, by default, only assumes .js files.
// !!! This ensures that TS -> JS module resolution works the same way.
'app-libs': path.resolve(__dirname, 'src/libs/')
},
},
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" },
// Static Artifacts retaining Paths
{
test: /\.(css|png|jpg|json|html)$/,
use: {
loader: 'file-loader',
options: {
name: '[path][name].[ext]'
}
}
}
]
},
plugins: [
// new UglifyJsPlugin({
// sourceMap: true
// })
]
};
module.exports = config;
// !!! BUNDLING
// !!! webpack will search in node-modules for non-relative paths (but also look at the alias above)
require('jquery');
// !!! not very well exposed -- but this method of the webpack API allows you to
// !!! include multiple files. It has an optional regex arg as well. In general,
// !!! I'd rather split and simplify directories than use complicated patterns.
require.context('./', true);
// !!! END BUNDLING
// !!! BOOTSTRAPPING
// !!! The output of this bundle - bundle.js is imported via <script> in index.html
// so the following gets executed then.
import Main from './index';
var m = new Main('ds-canvas');
Main.jq(document).ready(function() {
// wrap to get correct 'this'
m.runOnDocumentReady();
});
// !!! Entry Point class
// !!! node-modules import
import * as jq from 'jquery';
// !!! our own libs -- note the 'app-libs' aliasing we set in webpack.conf.js and tsconfig.json
import { Context2D, Renderer, Node } from 'app-libs/common';
import { TreeRenderer } from 'app-libs/tree';
import { LinkedList, ListRenderer } from 'app-libs/list';
export default class Main implements Renderer {
static jq: JQueryStatic = jq;
canvasId: string;
ctx2d: Context2D;
l: LinkedList<string>;
constructor(canvasId: string) {
console.log(`Initialising canvasId[${canvasId}]`);
this.canvasId = `#${canvasId}`;
}
runOnDocumentReady() {
console.log("Running.");
console.log("Adding Items.");
this.l = LinkedList.of(['1', '66', '44', '999']);
console.log("Traversing Items.");
this.l.traverse((n: Node<string>) => { console.log(`-> ${n.key}`) });
this.ctx2d = this.getCanvas().getContext('2d');
console.log(this.ctx2d);
this.draw(this.ctx2d);
}
draw(ctx2d: Context2D) {
new ListRenderer<string>(this.l).draw(ctx2d);
}
private getCanvas(): HTMLCanvasElement {
let e: any = jq(this.canvasId)[0];
if (e instanceof HTMLCanvasElement) {
return e;
}
throw new Error(`${this.canvasId} is not a canvas element.`);
}
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<canvas id="ds-canvas" width="1024" height="2048"></canvas>
<script type="text/javascript" src="/bundles/bundle.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment