README (README.md)
TensorFlow.js Examples
This repository contains a set of examples implemented in
TensorFlow.js.
Each example directory is standalone so the directory can be copied
to another project.
Overview of Examples
<table>
<tr>
<th>Example name</th>
<th>Demo link</th>
<th>Input data type</th>
<th>Task type</th>
<th>Model type</th>
<th>Training</th>
<th>Inference</th>
<th>API type</th>
<th>Save-load operations</th>
<tr>
<td><a href="./abalone-node">abalone-node</a></td>
<td></td>
<td>Numeric</td>
<td>Loading data from local file and training in Node.js</td>
<td>Multilayer perceptron</td>
<td>Node.js</td>
<td>Node.js</td>
<td>Layers</td>
<td>Saving to filesystem and loading in Node.js</td>
</tr>
<tr>
<td><a href="./addition-rnn">addition-rnn</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/addition-rnn/dist/index.html">🔗</a></td>
<td>Text</td>
<td>Sequence-to-sequence</td>
<td>RNN: SimpleRNN, GRU and LSTM</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./addition-rnn-webworker">addition-rnn-webworker</a></td>
<td></td>
<td>Text</td>
<td>Sequence-to-sequence</td>
<td>RNN: SimpleRNN, GRU and LSTM</td>
<td>Browser: Web Worker</td>
<td>Browser: Web Worker</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./angular-predictive-prefetching">angular-predictive-prefetching</a></td>
<td></td>
<td>Numeric</td>
<td>Multiclass predictor</td>
<td>DNN</td>
<td></td>
<td>Browser: Service Worker</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./baseball-node">baseball-node</a></td>
<td></td>
<td>Numeric</td>
<td>Multiclass classification</td>
<td>Multilayer perceptron</td>
<td>Node.js</td>
<td>Node.js</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./boston-housing">boston-housing</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/boston-housing/dist/index.html">🔗</a></td>
<td>Numeric</td>
<td>Regression</td>
<td>Multilayer perceptron</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./cart-pole">cart-pole</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/cart-pole/dist/index.html">🔗</a></td>
<td></td>
<td>Reinforcement learning</td>
<td>Policy gradient</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td>IndexedDB</td>
</tr>
<tr>
<td><a href="./chrome-extension">chrome-extension</a></td>
<td></td>
<td>Image</td>
<td>(Deploying TF.js in Chrome extension)</td>
<td>Convnet</td>
<td></td>
<td>Browser</td>
<td></td>
<td></td>
</tr>
<tr>
<td><a href="./custom-layer">custom-layer</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/custom-layer/dist/index.html">🔗</a></td>
<td></td>
<td>(Defining a custom Layer subtype)</td>
<td></td>
<td></td>
<td>Browser</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./data-csv">data-csv</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/data-csv/dist/index.html">🔗</a></td>
<td></td>
<td>Building a tf.data.Dataset from a remote CSV</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><a href="./data-generator">data-generator</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/data-generator/dist/index.html">🔗</a></td>
<td></td>
<td>Building a tf.data.Dataset using a generator</td>
<td>Regression</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./date-conversion-attention">date-conversion-attention</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/date-conversion-attention/dist/index.html">🔗</a></td>
<td>Text</td>
<td>Text-to-text conversion</td>
<td>Attention mechanism, RNN</td>
<td>Node.js</td>
<td>Browser and Node.js</td>
<td>Layers</td>
<td>Saving to filesystem and loading in browser</td>
</tr>
<tr>
<td><a href="./electron">electron</a></td>
<td></td>
<td>Image</td>
<td>(Deploying TF.js in Electron-based desktop apps)</td>
<td>Convnet</td>
<td></td>
<td>Node.js</td>
<td></td>
<td></td>
</tr>
<tr>
<td><a href="./fashion-mnist-vae">fashion-mnist-vae</a></td>
<td></td>
<td>Image</td>
<td>Generative</td>
<td>Variational autoencoder (VAE)</td>
<td>Node.js</td>
<td>Browser</td>
<td>Layers</td>
<td>Export trained model from tfjs-node and load it in browser</td>
</tr>
<tr>
<td><a href="./interactive-visualizers">interactive-visualizers</a></td>
<td></td>
<td>Image</td>
<td>Multiclass classification, object detection, segmentation</td>
<td></td>
<td></td>
<td>Browser</td>
<td></td>
<td></td>
</tr>
<tr>
<td><a href="./iris">iris</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/iris/dist/index.html">🔗</a></td>
<td>Numeric</td>
<td>Multiclass classification</td>
<td>Multilayer perceptron</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./iris-fitDataset">iris-fitDataset</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/iris-fitDataset/dist/index.html">🔗</a></td>
<td>Numeric</td>
<td>Multiclass classification</td>
<td>Multilayer perceptron</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./jena-weather">jena-weather</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/jena-weather/dist/index.html">🔗</a></td>
<td>Sequence</td>
<td>Sequence-to-prediction</td>
<td>MLP and RNNs</td>
<td>Browser and Node</td>
<td>Browser</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./lstm-text-generation">lstm-text-generation</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/lstm-text-generation/dist/index.html">🔗</a></td>
<td>Text</td>
<td>Sequence prediction</td>
<td>RNN: LSTM</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td>IndexedDB</td>
</tr>
<tr>
<td><a href="./mnist">mnist</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/mnist/dist/index.html">🔗</a></td>
<td>Image</td>
<td>Multiclass classification</td>
<td>Convolutional neural network</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./mnist-acgan">mnist-acgan</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/mnist-acgan/dist/index.html">🔗</a></td>
<td>Image</td>
<td>Generative Adversarial Network (GAN)</td>
<td>Convolutional neural network; GAN</td>
<td>Node.js</td>
<td>Browser</td>
<td>Layers</td>
<td>Saving to filesystem from Node.js and loading it in the browser</td>
</tr>
<tr>
<td><a href="./mnist-core">mnist-core</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/mnist-core/dist/index.html">🔗</a></td>
<td>Image</td>
<td>Multiclass classification</td>
<td>Convolutional neural network</td>
<td>Browser</td>
<td>Browser</td>
<td>Core (Ops)</td>
<td></td>
</tr>
<tr>
<td><a href="./mnist-node">mnist-node</a></td>
<td></td>
<td>Image</td>
<td>Multiclass classification</td>
<td>Convolutional neural network</td>
<td>Node.js</td>
<td>Node.js</td>
<td>Layers</td>
<td>Saving to filesystem</td>
</tr>
<tr>
<td><a href="./mnist-transfer-cnn">mnist-transfer-cnn</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/mnist-transfer-cnn/dist/index.html">🔗</a></td>
<td>Image</td>
<td>Multiclass classification (transfer learning)</td>
<td>Convolutional neural network</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td>Loading pretrained model</td>
</tr>
<tr>
<td><a href="./mobilenet">mobilenet</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/mobilenet/dist/index.html">🔗</a></td>
<td>Image</td>
<td>Multiclass classification</td>
<td>Convolutional neural network</td>
<td></td>
<td>Browser</td>
<td>Layers</td>
<td>Loading pretrained model</td>
</tr>
<tr>
<td><a href="./polynomial-regression">polynomial-regression</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/polynomial-regression/dist/index.html">🔗</a></td>
<td>Numeric</td>
<td>Regression</td>
<td>Shallow neural network</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./polynomial-regression-core">polynomial-regression-core</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/polynomial-regression-core/dist/index.html">🔗</a></td>
<td>Numeric</td>
<td>Regression</td>
<td>Shallow neural network</td>
<td>Browser</td>
<td>Browser</td>
<td>Core (Ops)</td>
<td></td>
</tr>
<tr>
<td><a href="./quantization">quantization</a></td>
<td></td>
<td>Various</td>
<td>Demonstrates the effect of post-training weight quantization</td>
<td>Various</td>
<td>Node.js</td>
<td>Node.js</td>
<td>Layers</td>
<td></td>
</tr>
<tr>
<td><a href="./sentiment">sentiment</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/sentiment/dist/index.html">🔗</a></td>
<td>Text</td>
<td>Sequence-to-binary-prediction</td>
<td>LSTM, 1D convnet</td>
<td>Node.js or Python</td>
<td>Browser</td>
<td>Layers</td>
<td>Load model from Keras and tfjs-node</td>
</tr>
<tr>
<td><a href="./simple-object-detection">simple-object-detection</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/simple-object-detection/dist/index.html">🔗</a></td>
<td>Image</td>
<td>Object detection</td>
<td>Convolutional neural network (transfer learning)</td>
<td>Node.js</td>
<td>Browser</td>
<td>Layers</td>
<td>Export trained model from tfjs-node and load it in browser</td>
</tr>
<tr>
<td><a href="./snake-dqn">snake-dqn</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/snake-dqn/index.html">🔗</a></td>
<td></td>
<td>Reinforcement learning</td>
<td>Deep Q-Network (DQN)</td>
<td>Node.js</td>
<td>Browser</td>
<td>Layers</td>
<td>Export trained model from tfjs-node and load it in browser</td>
</tr>
<tr>
<td><a href="./translation">translation</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/translation/dist/index.html">🔗</a></td>
<td>Text</td>
<td>Sequence-to-sequence</td>
<td>LSTM encoder and decoder</td>
<td>Node.js or Python</td>
<td>Browser</td>
<td>Layers</td>
<td>Load model converted from Keras</td>
</tr>
<tr>
<td><a href="./tsne-mnist-canvas">tsne-mnist-canvas</a></td>
<td></td>
<td></td>
<td>Dimension reduction and data visualization</td>
<td>tSNE</td>
<td>Browser</td>
<td>Browser</td>
<td>Core (Ops)</td>
<td></td>
</tr>
<tr>
<td><a href="./webcam-transfer-learning">webcam-transfer-learning</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/webcam-transfer-learning/dist/index.html">🔗</a></td>
<td>Image</td>
<td>Multiclass classification (transfer learning)</td>
<td>Convolutional neural network</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td>Loading pretrained model</td>
</tr>
<tr>
<td><a href="./website-phishing">website-phishing</a></td>
<td><a href="https://storage.googleapis.com/tfjs-examples/website-phishing/dist/index.html">🔗</a></td>
<td>Numeric</td>
<td>Binary classification</td>
<td>Multilayer perceptron</td>
<td>Browser</td>
<td>Browser</td>
<td>Layers</td>
<td></td>
</tr>
</table>
Dependencies
Except for getting_started, all the examples require the following dependencies to be installed.
- Node.js version 8.9 or higher
- NPM cli OR Yarn
How to build an example
cd into the directoryIf you are using yarn:
cd mnist-core
yarn
yarn watchIf you are using npm:
cd mnist-core
npm install
npm run watchDetails
The convention is that each example contains two scripts:
- yarn watch or npm run watch: starts a local development HTTP server which watches the
filesystem for changes so you can edit the code (JS or HTML) and see changes when you refresh the page immediately.
- yarn build or npm run build: generates a dist/ folder which contains the build artifacts and
can be used for deployment.
Contributing
If you want to contribute an example, please reach out to us on
Github issues
before sending us a pull request as we are trying to keep this set of examples
small and highly curated.
Running Presubmit Tests
Before you send a pull request, it is a good idea to run the presubmit tests
and make sure they all pass. To do that, execute the following commands in the
root directory of tfjs-examples:
yarn
yarn presubmitThe yarn presubmit command executes the unit tests and lint checks of all
the exapmles that contain the yarn test and/or yarn lint scripts. You
may also run the tests for individual exampls by cd'ing into their respective
subdirectory and executing yarn, followed by yarn test and/or yarn lint.
---
Cloudbuild.Yml (cloudbuild.yml)
steps:
- name: 'gcr.io/learnjs-174218/release'
entrypoint: 'yarn'
id: 'yarn'
args: ['install']
- name: 'gcr.io/learnjs-174218/release'
entrypoint: 'yarn'
id: 'test'
args: ['presubmit']
waitFor: ['yarn']
env: ['BROWSERSTACK_USERNAME=deeplearnjs1']
secretEnv: ['BROWSERSTACK_KEY']
secrets:
- kmsKeyName: projects/learnjs-174218/locations/global/keyRings/tfjs/cryptoKeys/enc
secretEnv:
BROWSERSTACK_KEY: CiQAkwyoIW0LcnxymzotLwaH4udVTQFBEN4AEA5CA+a3+yflL2ASPQAD8BdZnGARf78MhH5T9rQqyz9HNODwVjVIj64CTkFlUCGrP1B2HX9LXHWHLmtKutEGTeFFX9XhuBzNExA=
timeout: 1800s
logsBucket: 'gs://tfjs-build-logs'
options:
logStreamingOption: 'STREAM_ON'
machineType: 'N1_HIGHCPU_8'
substitution_option: 'ALLOW_LOOSE'
---
CONTRIBUTING (CONTRIBUTING.md)
How to Contribute
We'd love to accept your patches and contributions to this project. There are
just a few small guidelines you need to follow.
Contributor License Agreement
Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution,
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to <https://cla.developers.google.com/> to see
your current agreements on file or to sign a new one.
You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
Code reviews
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
GitHub Help for more
information on using pull requests.
We require unit tests for most code, instructions for running our unit test
suites are in the documentation.
Content
Generally speaking, we are trying to keep this list to a small set of
high-quality, curated examples. If you want to add a new example, please
consult with us (in Github Issues) before creating a new example. We don't
want to see you go through all of the work of creating a new example and us not
being in a place to accept it.
We certainly invite you to create examples and post them on Github for others
to learn from. You can share your progress with others in community in Github
Issues.
---
Package.Json (package.json)
{
"name": "tfjs-examples",
"version": "0.0.1",
"scripts": {
"presubmit": "ts-node presubmit.ts"
},
"devDependencies": {
"@types/node": "~18.15.11",
"@types/shelljs": "~0.8.11",
"fs": "~0.0.1-security",
"jasmine": "~3.10.0",
"shelljs": "0.8.5",
"ts-node": "~10.9.1",
"tslint": "~6.1.3",
"tslint-no-circular-imports": "~0.7.0",
"typescript": "4.8.3",
"yalc": "~1.0.0-pre.53"
},
"resolutions": {
"path-parse": "1.0.7"
},
"license": "Apache-2.0"
}
---
Abalone Node/README (abalone-node/README.md)
TensorFlow.js Example: Abalone Age
This example shows how to predict the age of abalone from physical measurements using TensorFlow.js with Node.js.
The data set available at UCI Machine Learning Repository.
This example shows how to:
* load a Dataset from a local csv file.
* prepare the Dataset for training.
* create a tf.LayersModel from scratch.
* train the model through model.fitDataset().
* save the trained model to a local folder.
To launch the demo, run the following command:
yarn
yarn trainThe result logs 100 Epochs as well as a predicted result similar to the following:
...
Epoch 100 / 100
eta=0.0 =================================================>
402ms 57414us/step - loss=7.42 val_loss=5.60
The actual test abalone age is 10, the inference result from the model is 11.929240226745605By default, the training uses tfjs-node, which runs on the CPU.
If you have a CUDA-enabled GPU and have the CUDA and CuDNN libraries
set up properly on your system, you can run the training on the GPU
by replacing the tfjs-node package with tfjs-node-gpu.
---
Abalone Node/Package.Json (abalone-node/package.json)
{
"name": "tfjs-abalone-node",
"version": "1.0.0",
"description": "",
"main": "index.js",
"license": "Apache-2.0",
"scripts": {
"train": "node train.js",
"test": "node run_tests.js"
},
"dependencies": {
"@tensorflow/tfjs-node": "^2.6.0",
"argparse": "^1.0.10"
},
"devDependencies": {
"jasmine": "^3.2.0",
"jasmine-core": "^3.2.1",
"shelljs": "^0.8.5",
"tmp": "^0.0.33"
}
}
---
Abalone Node/TrainedModel/Model.Json (abalone-node/trainedModel/model.json)
{"modelTopology":{"class_name":"Sequential","config":{"name":"sequential_1","layers":[{"class_name":"Dense","config":{"units":50,"activation":"sigmoid","use_bias":true,"kernel_initializer":{"class_name":"VarianceScaling","config":{"scale":1,"mode":"fan_avg","distribution":"normal","seed":null}},"bias_initializer":{"class_name":"Zeros","config":{}},"kernel_regularizer":null,"bias_regularizer":null,"activity_regularizer":null,"kernel_constraint":null,"bias_constraint":null,"name":"dense_Dense1","trainable":true,"batch_input_shape":[null,8],"dtype":"float32"}},{"class_name":"Dense","config":{"units":50,"activation":"sigmoid","use_bias":true,"kernel_initializer":{"class_name":"VarianceScaling","config":{"scale":1,"mode":"fan_avg","distribution":"normal","seed":null}},"bias_initializer":{"class_name":"Zeros","config":{}},"kernel_regularizer":null,"bias_regularizer":null,"activity_regularizer":null,"kernel_constraint":null,"bias_constraint":null,"name":"dense_Dense2","trainable":true}},{"class_name":"Dense","config":{"units":1,"activation":"linear","use_bias":true,"kernel_initializer":{"class_name":"VarianceScaling","config":{"scale":1,"mode":"fan_avg","distribution":"normal","seed":null}},"bias_initializer":{"class_name":"Zeros","config":{}},"kernel_regularizer":null,"bias_regularizer":null,"activity_regularizer":null,"kernel_constraint":null,"bias_constraint":null,"name":"dense_Dense3","trainable":true}}]},"keras_version":"tfjs-layers 1.3.2","backend":"tensor_flow.js"},"weightsManifest":[{"paths":["weights.bin"],"weights":[{"name":"dense_Dense1/kernel","shape":[8,50],"dtype":"float32"},{"name":"dense_Dense1/bias","shape":[50],"dtype":"float32"},{"name":"dense_Dense2/kernel","shape":[50,50],"dtype":"float32"},{"name":"dense_Dense2/bias","shape":[50],"dtype":"float32"},{"name":"dense_Dense3/kernel","shape":[50,1],"dtype":"float32"},{"name":"dense_Dense3/bias","shape":[1],"dtype":"float32"}]}],"format":"layers-model","generatedBy":"TensorFlow.js tfjs-layers v1.3.2","convertedBy":null}
---
Addition Rnn/README (addition-rnn/README.md)
TensorFlow.js Example: Addition RNN
This example uses an RNN to compute the addition of two integers by doing
string => string translation. Obviously it's not the best way to add two
numbers, but it makes a fun example.
Note: this example is a port of the Keras addition RNN example with a UI.
You can find the original Keras python code here.
To run this demo locally on your machine, run the following commands:
yarn
yarn watchThe demo runs on port http://localhost:1234.
Once the page loads, click Train model to train. You can view the model's progress through graphs displayed on the page.
Upon completion of training, view the model's success through displayed test examples.
---
Addition Rnn/Package.Json (addition-rnn/package.json)
{
"name": "tfjs-examples-addition-rnn",
"version": "0.1.0",
"description": "",
"main": "index.js",
"license": "Apache-2.0",
"private": true,
"engines": {
"node": ">=8.9.0"
},
"dependencies": {
"@tensorflow/tfjs": "^3.3.0",
"@tensorflow/tfjs-vis": "^1.5.0"
},
"scripts": {
"watch": "cross-env NODE_ENV=development parcel index.html --no-hmr --open",
"build": "cross-env NODE_ENV=production parcel build --no-scope-hoist index.html --public-url ./",
"link-local": "yalc link"
},
"devDependencies": {
"buffer": "^6.0.3",
"clang-format": "~1.2.2",
"cross-env": "^5.1.6",
"parcel": "~2.3.2",
"process": "^0.11.10",
"yalc": "~1.0.0-pre.50"
}
}
---
Addition Rnn Webworker/README (addition-rnn-webworker/README.md)
TensorFlow.js Example: Addition RNN in Webworker
This example uses an RNN to compute (in a worker thread) the addition of two integers by doing
string => string translation. Obviously it's not the best way to add two
numbers, but it makes a fun example. In this way, we can do long-running computation without blocking the UI thread.
Note: This example is based on the addition-rnn example in this repo, which is based on the original Keras python code here
---
Addition Rnn Webworker/Package.Json (addition-rnn-webworker/package.json)
{
"name": "tfjs-examples-addition-rnn",
"version": "0.1.0",
"description": "",
"main": "index.js",
"license": "Apache-2.0",
"private": true,
"engines": {
"node": ">=8.9.0"
},
"dependencies": {
"@tensorflow/tfjs": "^1.3.2",
"@tensorflow/tfjs-vis": "^1.1.0"
},
"scripts": {
"watch": "cross-env NODE_ENV=development parcel index.html --no-hmr --open",
"build": "cross-env NODE_ENV=production parcel build --no-scope-hoist index.html --public-url ./",
"link-local": "yalc link"
},
"devDependencies": {
"buffer": "^6.0.3",
"clang-format": "~1.2.2",
"cross-env": "^5.1.6",
"parcel": "~2.3.2",
"process": "^0.11.10",
"yalc": "~1.0.0-pre.50"
}
}
---
Angular Predictive Prefetching/README (angular-predictive-prefetching/README.md)
Angular Predictive Prefetching
This examples shows a sample implementation of predictive prefetching with TensorFlow.js and Angular. You can find more information about how the entire end-to-end solution works in the blog post "Speed-up your sites with web-page prefetching using Machine Learning."
The demo is inspired by the Google Merchandise Store, but does not share any data nor implementation details with it.
Setup
To try the example yourself, go through the following steps:
* Install the dependencies of the client and the server:
cd client && yarn
cd ../server && yarn* Start the server. In a terminal window run:
cd server && yarn start* Start the client. In a terminal window run:
cd client && yarn build
cd dist/merch-store
npx serve -s .When you open the browser (by default http://localhost:5000) and navigate through the application in Chrome DevTools you should see logs similar to:
<p align="center">
<img src="./assets/console.png">
</p>
You can track the activity in the "Network" panel to find the requests the service worker makes based on the predictions:
<p align="center">
<img src="./assets/network.png">
</p>
License
MIT
---
Angular Predictive Prefetching/Client/Angular.Json (angular-predictive-prefetching/client/angular.json)
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"merch-store": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/merch-store",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets",
"src/prefetch.service-worker.js"
],
"styles": [
"src/styles.scss"
],
"stylePreprocessorOptions": {
"includePaths": [
"node_modules/"
]
},
"scripts": [
],
"webWorkerTsConfig": "tsconfig.worker.json"
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "merch-store:build"
},
"configurations": {
"production": {
"browserTarget": "merch-store:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "merch-store:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets",
"src/prefetch.service-worker.js"
],
"styles": [
"src/styles.scss"
],
"stylePreprocessorOptions": {
"includePaths": [
"node_modules/"
]
},
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json",
"tsconfig.worker.json"
],
"exclude": [
"/node_modules/"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "merch-store:serve"
},
"configurations": {
"production": {
"devServerTarget": "merch-store:serve:production"
}
}
},
"deploy": {
"builder": "@angular/fire:deploy",
"options": {}
}
}
}
},
"defaultProject": "merch-store"
}
---
Angular Predictive Prefetching/Client/Package.Json (angular-predictive-prefetching/client/package.json)
{
"name": "gstore",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --configuration production",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~11.2.4",
"@angular/cdk": "^11.2.3",
"@angular/common": "~11.2.4",
"@angular/compiler": "~11.2.4",
"@angular/core": "~11.2.4",
"@angular/forms": "~11.2.4",
"@angular/material": "^11.2.5",
"@angular/material-experimental": "^11.2.5",
"@angular/platform-browser": "~11.2.4",
"@angular/platform-browser-dynamic": "~11.2.4",
"@angular/router": "~11.2.4",
"express": "^4.17.3",
"material-components-web": "11.0.0-canary.3201cae47.0",
"rxjs": "~6.5.5",
"tslib": "^2.0.0",
"zone.js": "~0.10.3"
},
"devDependencies": {
"@angular-devkit/architect": ">= 0.900 < 0.1200",
"@angular-devkit/build-angular": "~0.1102.3",
"@angular/cli": "~11.2.3",
"@angular/compiler-cli": "~11.2.4",
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
"fuzzy": "^0.1.3",
"inquirer": "^6.2.2",
"inquirer-autocomplete-prompt": "^1.0.1",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~6.3.16",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"open": "^7.0.3",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"typescript": "~4.1.5"
}
}
---
Angular Predictive Prefetching/Client/Tsconfig.App.Json (angular-predictive-prefetching/client/tsconfig.app.json)
/ To learn more about this file see: https://angular.io/config/tsconfig. /
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts",
"src/polyfills.ts"
],
"include": [
"src//*.d.ts"
]
}
---
Angular Predictive Prefetching/Client/Tsconfig.Json (angular-predictive-prefetching/client/tsconfig.json)
/ To learn more about this file see: https://angular.io/config/tsconfig. /
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"module": "es2020",
"lib": [
"es2018",
"dom"
],
"resolveJsonModule": true,
}
}
---
Angular Predictive Prefetching/Client/Tsconfig.Spec.Json (angular-predictive-prefetching/client/tsconfig.spec.json)
/ To learn more about this file see: https://angular.io/config/tsconfig. /
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
]
},
"files": [
"src/test.ts",
"src/polyfills.ts"
],
"include": [
"src//*.spec.ts",
"src//*.d.ts"
]
}
---
Angular Predictive Prefetching/Client/Tsconfig.Worker.Json (angular-predictive-prefetching/client/tsconfig.worker.json)
/ To learn more about this file see: https://angular.io/config/tsconfig. /
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/worker",
"lib": [
"es2018",
"webworker"
],
"types": []
},
"include": [
"src//*.worker.ts"
]
}
---
Angular Predictive Prefetching/Client/Tslint.Json (angular-predictive-prefetching/client/tslint.json)
{
"extends": "tslint:recommended",
"rules": {
"align": {
"options": [
"parameters",
"statements"
]
},
"array-type": false,
"arrow-return-shorthand": true,
"curly": true,
"deprecation": {
"severity": "warning"
},
"component-class-suffix": true,
"contextual-lifecycle": true,
"directive-class-suffix": true,
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
],
"eofline": true,
"import-blacklist": [
true,
"rxjs/Rx"
],
"import-spacing": true,
"indent": {
"options": [
"spaces"
]
},
"max-classes-per-file": false,
"max-line-length": [
true,
140
],
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
---