Skip to content

Commit

Permalink
Add documentation and example code for projectReferences (#1184)
Browse files Browse the repository at this point in the history
* Added Project References documentation and example

* Fix links & Typos

* Clarify relationship between ts-laoder and tsc
  • Loading branch information
appzuka committed Sep 14, 2020
1 parent 46d9761 commit f8eba53
Show file tree
Hide file tree
Showing 21 changed files with 5,139 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -713,6 +713,8 @@ This flag enables caching for some FS-functions like `fileExists`, `realpath` an

ts-loader has opt-in support for [project references](https://www.typescriptlang.org/docs/handbook/project-references.html). With this configuration option enabled, `ts-loader` will incrementally rebuild upstream projects the same way `tsc --build` does. Otherwise, source files in referenced projects will be treated as if they’re part of the root project.

In order to make use of this option your project needs to be correctly configured to build the project references and then to use them as part of the build. See the [Project References Guide](REFERENCES.md) and the example code in the examples which can be found [here](examples/project-references-example/).

### Usage with webpack watch

Because TS will generate .js and .d.ts files, you should ignore these files, otherwise watchers may go into an infinite watch loop. For example, when using webpack, you may wish to add this to your webpack.conf.js file:
Expand Down
331 changes: 331 additions & 0 deletions REFERENCES.md

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions examples/project-references-example/.gitignore
@@ -0,0 +1,5 @@
lib/
node_modules/
dist/
tsconfig.tsbuildinfo

24 changes: 24 additions & 0 deletions examples/project-references-example/README.md
@@ -0,0 +1,24 @@
# TypeScript Project References Demo

This repo is forked from https://github.com/RyanCavanaugh/project-references-demo, which is a repo to demonstrate the use of project references in TypeScript. It has been extended to show how project references can be used in a project using the following:

* TypeScript
* Webpack
* ts-loader
* yarn workspaces

This repo is described in the article [here](/REFERENCES.md).

## Installation
```
yarn install
```

## Running
```
yarn start
```
Go to localhost:8080 in your browser to view the output. Edit files in the <code>packages</code> to see the changes in the browser.



36 changes: 36 additions & 0 deletions examples/project-references-example/package.json
@@ -0,0 +1,36 @@
{
"name": "project-references-demo",
"version": "1.0.0",
"description": "To compare the performance of project references with webpack & ts-loader vs webpack and tsc run in a separate process.",
"main": "index.js",
"private": true,
"workspaces": ["packages/*"],
"scripts": {
"start": "webpack-dev-server",
"build": "webpack"
},
"repository": {
"type": "git",
"url": "git+https://github.com/appzuka/project-references-demo.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/appzuka/project-references-demo.git/issues"
},
"homepage": "https://github.com/appzuka/project-references-demo.git",
"dependencies": {
"@types/node": "^14.6.1",
"@types/react": "^16.9.48",
"fork-ts-checker-webpack-plugin": "^5.1.0",
"html-webpack-plugin": "^4.4.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"ts-loader": "^8.0.3",
"tsconfig-paths-webpack-plugin": "^3.3.0",
"typescript": "^3.9.7",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0"
}
}
10 changes: 10 additions & 0 deletions examples/project-references-example/packages/animals/animal.ts
@@ -0,0 +1,10 @@
type Size = "small" | "medium" | "large";

interface Animal {
size: Size;
}

export {
Animal,
Size
}
28 changes: 28 additions & 0 deletions examples/project-references-example/packages/animals/dog.tsx
@@ -0,0 +1,28 @@
import { Animal, Size } from './animal';
import { makeRandomName } from '@myscope/core';

interface Dog extends Animal {
woof(): void;
name: string;
}

const sizes = "small medium large".split(' ');
const barks = "Woof Yap Growl".split(' ');

function createDog(): Dog {
return ({
size: sizes[Math.floor(Math.random() * sizes.length)] as Size,
woof: function(this: Dog) {
return(`${this.name} says ${barks[Math.floor(Math.random() * barks.length)]}!`);
},
name: makeRandomName(),
// deliberateError: 42
});
}

export {
Dog,
createDog
}


4 changes: 4 additions & 0 deletions examples/project-references-example/packages/animals/index.ts
@@ -0,0 +1,4 @@
import { Animal } from './animal';

import { createDog, Dog } from './dog';
export { Animal, createDog, Dog };
10 changes: 10 additions & 0 deletions examples/project-references-example/packages/animals/package.json
@@ -0,0 +1,10 @@
{
"name": "@myscope/animals",
"version": "1.0.0",
"description": "Animals package",
"main": "lib/index.js",
"directories": {
"lib": "lib"
},
"license": "ISC"
}
10 changes: 10 additions & 0 deletions examples/project-references-example/packages/animals/tsconfig.json
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig-base.json",
"compilerOptions": {
"outDir": "lib",
"rootDir": ".",
},
"references": [
{ "path": "../core" }
]
}
10 changes: 10 additions & 0 deletions examples/project-references-example/packages/core/package.json
@@ -0,0 +1,10 @@
{
"name": "@myscope/core",
"version": "1.0.0",
"description": "Core package",
"main": "lib/utilities.js",
"directories": {
"lib": "lib"
},
"license": "ISC"
}
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig-base.json",
"compilerOptions": {
"outDir": "lib",
"rootDir": "."
}
}
17 changes: 17 additions & 0 deletions examples/project-references-example/packages/core/utilities.ts
@@ -0,0 +1,17 @@

const dogNames = "Baxter Bear Beau Benji Benny Benny Bentley Blue Bo Boomer Brady Brody Bruno Brutus Bubba Buddy Buster Cash Champ Chance Charlie Chase Chester Chico Coco Cody Cooper Copper Dexter Diesel Duke Elvis Finn Frankie George Gizmo Gunner Gus Hank Harley Henry Hunter Jack Jackson Jake Jasper Jax Joey Kobe Leo Loki Louie Lucky Luke Mac Marley Max Mickey Milo Moose Murphy Oliver Ollie Oreo Oscar Otis Peanut Prince Rex Riley Rocco Rocky Romeo Roscoe Rudy Rufus Rusty Sam Sammy Samson Scooter Scout Shadow Simba Sparky Spike Tank Teddy Thor Toby Tucker Tyson Vader Winston Yoda Zeus Ziggy".split(' ');

function makeRandomName() {
return dogNames[Math.floor(Math.random() * dogNames.length)];
}

function lastElementOf<T>(arr: T[]): T | undefined {
if (arr.length === 0) return undefined;
return arr[arr.length - 1];
}

export {
makeRandomName,
lastElementOf
}

10 changes: 10 additions & 0 deletions examples/project-references-example/packages/zoo/package.json
@@ -0,0 +1,10 @@
{
"name": "@myscope/zoo",
"version": "1.0.0",
"description": "Zoo package",
"main": "lib/zoo.js",
"directories": {
"lib": "lib"
},
"license": "ISC"
}
13 changes: 13 additions & 0 deletions examples/project-references-example/packages/zoo/tsconfig.json
@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig-base.json",
"compilerOptions": {
"outDir": "lib",
"jsx": "react",
"rootDir": ".",
},
"references": [
{
"path": "../animals"
}
]
}
31 changes: 31 additions & 0 deletions examples/project-references-example/packages/zoo/zoo.tsx
@@ -0,0 +1,31 @@
import React from 'react';
import { Dog, createDog } from '@myscope/animals';

function CreateZoo() {

const dogs = [
createDog(),
createDog(),
createDog(),
createDog(),
createDog(),
createDog(),
createDog()
];
return (<>
<h2>List of Dogs</h2>
<hr />
{dogs.map((dog, i) => {return(
<div className='dog' key={i}>
<p>Dog: {i} - Size: {dog.size} - Name: {dog.name}</p>
<p>Bark: {dog.woof()}</p>
<hr />
</div>
)})}
</>)
}

export {
CreateZoo
}

8 changes: 8 additions & 0 deletions examples/project-references-example/src/index.tsx
@@ -0,0 +1,8 @@
import { CreateZoo } from '@myscope/zoo';
import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
<CreateZoo />,
document.getElementById('react-content')
);
16 changes: 16 additions & 0 deletions examples/project-references-example/tsconfig-base.json
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"composite": true,
"jsx": "react",
"baseUrl": ".", // This must be specified if "paths" is.
"paths": {
"packages/*": ["packages/*"]
}
}
}
15 changes: 15 additions & 0 deletions examples/project-references-example/tsconfig.json
@@ -0,0 +1,15 @@
{
"extends": "./tsconfig-base.json",
"files": ["src/index.tsx"],
"references": [
{
"path": "./packages/core"
},
{
"path": "./packages/animals"
},
{
"path": "./packages/zoo"
}
]
}
62 changes: 62 additions & 0 deletions examples/project-references-example/webpack.config.js
@@ -0,0 +1,62 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
// To improve build times for large projects enable fork-ts-checker-webpack-plugin
// const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

module.exports = {
"mode": "development",
"entry": "src/index.tsx",
"output": {
"path": __dirname+'/dist',
"filename": "[name].js"
},
"watch": false,
"context": __dirname, // to automatically find tsconfig.json
"module": {
"rules": [
{
"test": /\.tsx?$/,
"exclude": /node_modules/,
"use": {
"loader": "ts-loader",
"options": {
"transpileOnly": false, // Set to true if you are using fork-ts-checker-webpack-plugin
"projectReferences": true
}
}
}
]
},
resolve: {
modules: [
"node_modules",
path.resolve(__dirname)
],
// TsconfigPathsPlugin will automatically add this
// alias: {
// packages: path.resolve(__dirname, 'packages/'),
// },
extensions: [".js", ".ts", ".tsx"],
plugins: [
new TsconfigPathsPlugin({
logLevel: "info",
mainFields: "module",
extensions: [".js", ".ts", ".tsx"]
})
]
},
plugins: [
new HtmlWebpackPlugin({
templateContent: `
<html>
<body>
<h1>Project Reference Demo App</h1>
<div id='react-content'></div>
</body>
</html>
`
}),
// new ForkTsCheckerWebpackPlugin()
]
}

0 comments on commit f8eba53

Please sign in to comment.