├── .gitignore
├── README.md
├── config
├── helpers.js
├── webpack.common.js
├── webpack.dev.js
├── webpack.prod.js
└── webpack.test.js
├── modules.d.ts
├── package-lock.json
├── package.json
├── src
├── app
│ ├── Position.ts
│ ├── app.html
│ ├── app.scss
│ ├── app.ts
│ ├── input.ts
│ └── squiggles
│ │ ├── Settings.ts
│ │ ├── State.ts
│ │ └── squiggle.ts
├── index.html
├── index.ts
├── package.ts
├── styles.scss
└── vendor.ts
├── tsconfig.json
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | /node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.sass-cache
29 | /connect.lock
30 | /coverage/*
31 | /libpeerconnection.log
32 | npm-debug.log
33 | testem.log
34 | /typings
35 |
36 | # e2e
37 | /e2e/*.js
38 | /e2e/*.map
39 |
40 | # System Files
41 | .DS_Store
42 | Thumbs.db
43 |
44 | yarn.lock
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SVG squiggles
2 | Colorful, mouse following, squiggles. Written with Typescript, GSAP and rxjs.
3 |
4 | Demo https://codepen.io/steveg3003/full/qobgBM/
5 |
6 | ### Getting started
7 | First you need to download the the packages
8 |
9 | ~~~~
10 | npm install
11 | ~~~~
12 |
13 | ### Development
14 | For development run
15 |
16 | ~~~~
17 | npm run start
18 | ~~~~
19 |
20 | Which will the app on http://localhost:3000 and will reload when you make changes
21 |
22 | ### Build
23 | To create a new build run
24 |
25 | ~~~~
26 | npm run build
27 | ~~~~
28 |
29 | Which will create a new version of the app in a 'dists' folder.
30 |
--------------------------------------------------------------------------------
/config/helpers.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var _root = path.resolve(__dirname, '..');
3 | function root(args) {
4 | args = Array.prototype.slice.call(arguments, 0);
5 | return path.join.apply(path, [_root].concat(args));
6 | }
7 | exports.root = root;
8 |
--------------------------------------------------------------------------------
/config/webpack.common.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var ExtractTextPlugin = require('extract-text-webpack-plugin');
4 | var helpers = require('./helpers');
5 |
6 | module.exports = {
7 | entry: {
8 | 'vendor': './src/vendor.ts',
9 | 'app': './src/index.ts'
10 | },
11 |
12 | resolve: {
13 | extensions: ['.js', '.ts']
14 | },
15 |
16 | module: {
17 | loaders: [
18 | {
19 | test: /\.ts$/,
20 | loaders: ['awesome-typescript-loader']
21 | },
22 | {
23 | test: /\.html$/,
24 | loader: 'html-loader'
25 | },
26 | {
27 | test: /\.(png|jp(e*)g|svg)$/,
28 | use: [{
29 | loader: 'url-loader',
30 | options: {
31 | limit: 8000, // Convert images < 8kb to base64 strings
32 | name: 'images/[hash]-[name].[ext]'
33 | }
34 | }]
35 | },
36 | {
37 | test: /\.scss$/,
38 | use: [{
39 | loader: "style-loader" // creates style nodes from JS strings
40 | }, {
41 | loader: "css-loader" // translates CSS into CommonJS
42 | }, {
43 | loader: "sass-loader" // compiles Sass to CSS
44 | }]
45 | }
46 | ]
47 | },
48 |
49 | plugins: [
50 | new webpack.optimize.CommonsChunkPlugin({
51 | name: ['app', 'vendor']
52 | }),
53 |
54 | new HtmlWebpackPlugin({
55 | template: './src/index.html'
56 | }),
57 |
58 | new webpack.DefinePlugin({
59 | VERSION: JSON.stringify(process.env.npm_package_version),
60 | })
61 | ]
62 | };
63 |
--------------------------------------------------------------------------------
/config/webpack.dev.js:
--------------------------------------------------------------------------------
1 | var webpackMerge = require('webpack-merge');
2 | var ExtractTextPlugin = require('extract-text-webpack-plugin');
3 | var commonConfig = require('./webpack.common.js');
4 | var helpers = require('./helpers');
5 |
6 | module.exports = webpackMerge(commonConfig, {
7 | devtool: 'cheap-module-eval-source-map',
8 |
9 | output: {
10 | publicPath: 'http://localhost:3000/',
11 | filename: '[name].js',
12 | chunkFilename: '[id].chunk.js'
13 | },
14 |
15 | plugins: [
16 | new ExtractTextPlugin('[name].css')
17 | ],
18 |
19 | devServer: {
20 | historyApiFallback: true,
21 | stats: 'minimal'
22 | }
23 | });
24 |
--------------------------------------------------------------------------------
/config/webpack.prod.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var webpackMerge = require('webpack-merge');
3 | var ExtractTextPlugin = require('extract-text-webpack-plugin');
4 | var commonConfig = require('./webpack.common.js');
5 | var helpers = require('./helpers');
6 |
7 | const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
8 |
9 | module.exports = webpackMerge(commonConfig, {
10 | devtool: 'source-map',
11 |
12 | output: {
13 | path: helpers.root('dist'),
14 | publicPath: '/',
15 | filename: '[name].[hash].js',
16 | chunkFilename: '[id].[hash].chunk.js'
17 | },
18 |
19 | plugins: [
20 | new webpack.NoEmitOnErrorsPlugin(),
21 | new webpack.optimize.UglifyJsPlugin(),
22 | new ExtractTextPlugin('[name].[hash].css'),
23 | new webpack.DefinePlugin({
24 | 'process.env': {
25 | 'ENV': JSON.stringify(ENV)
26 | }
27 | })
28 | ]
29 | });
30 |
--------------------------------------------------------------------------------
/config/webpack.test.js:
--------------------------------------------------------------------------------
1 | var helpers = require('./helpers');
2 |
3 | module.exports = {
4 | devtool: 'inline-source-map',
5 |
6 | resolve: {
7 | extensions: ['.ts', '.js']
8 | },
9 |
10 | module: {
11 | loaders: [
12 | {
13 | test: /\.ts$/,
14 | loaders: ['awesome-typescript-loader']
15 | },
16 | {
17 | test: /\.html$/,
18 | loader: 'html'
19 |
20 | },
21 | {
22 | test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
23 | loader: 'null'
24 | },
25 | {
26 | test: /\.scss$/,
27 | loaders: ["style", "css", "sass", "scss"]
28 | }
29 | ]
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/modules.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.png'
2 | declare function require(string:string): string;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svg-squiggles",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --inline --progress --port 3000",
8 | "build": "rimraf docs && webpack --config config/webpack.prod.js --progress --profile --bail"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/ste-vg/svg-squiggles.git"
13 | },
14 | "keywords": [],
15 | "author": "",
16 | "license": "ISC",
17 | "bugs": {
18 | "url": "https://github.com/ste-vg/svg-squiggles/issues"
19 | },
20 | "homepage": "https://github.com/ste-vg/svg-squiggles#readme",
21 | "dependencies": {
22 | "gsap": "^1.20.4",
23 | "rxjs": "^5.5.7"
24 | },
25 | "devDependencies": {
26 | "@types/gsap": "^1.19.2",
27 | "awesome-typescript-loader": "^3.4.1",
28 | "css-loader": "^0.28.8",
29 | "extract-text-webpack-plugin": "^3.0.2",
30 | "file-loader": "^1.1.6",
31 | "fs": "0.0.1-security",
32 | "html-loader": "^0.5.4",
33 | "html-webpack-plugin": "^2.30.1",
34 | "node-sass": "^4.11.0",
35 | "rimraf": "^2.6.2",
36 | "sass-loader": "^6.0.6",
37 | "style-loader": "^0.19.1",
38 | "typescript": "^2.6.2",
39 | "url-loader": "^0.6.2",
40 | "webpack": "^3.10.0",
41 | "webpack-dev-server": "^2.10.0",
42 | "webpack-merge": "^4.1.1"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/app/Position.ts:
--------------------------------------------------------------------------------
1 | export interface Position
2 | {
3 | x: number,
4 | y: number
5 | }
--------------------------------------------------------------------------------
/src/app/app.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/app.scss:
--------------------------------------------------------------------------------
1 | path
2 | {
3 | //mix-blend-mode: color-dodge;
4 | }
--------------------------------------------------------------------------------
/src/app/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import './app.scss';
3 | import { Pkg } from "../package";
4 | import { Squiggle } from "./squiggles/squiggle";
5 | import { SquiggleSettings } from "./squiggles/Settings";
6 | import { SquiggleState } from './squiggles/State';
7 | import { Position } from './Position';
8 | import { Input } from './input';
9 |
10 | import { Observable } from "rxjs";
11 |
12 | const html = require('./app.html');
13 |
14 | export class App
15 | {
16 | private container:HTMLElement;
17 | private svg:HTMLElement;
18 | private squiggles:Squiggle[] = [];
19 |
20 | private width: number = 600;
21 | private height: number = 600;
22 |
23 | private lastMousePosition:Position;
24 | private direction:Position;
25 |
26 | private grid:number = 40;
27 |
28 | constructor(container:HTMLElement)
29 | {
30 | console.log(Pkg().version);
31 |
32 | this.container = container;
33 | this.container.innerHTML = html;
34 | this.svg = document.getElementById('stage');
35 | this.onResize();
36 |
37 | this.tick();
38 |
39 | let input = new Input(this.container);
40 |
41 | input.moves.subscribe((position:Position) =>
42 | {
43 | for(let i = 0; i < 3; i++) this.createSqwigFromMouse(position);
44 | })
45 |
46 | input.starts.subscribe((position:Position) => this.lastMousePosition = position)
47 | input.ends.subscribe((position:Position) => this.burst(true))
48 |
49 | if(location.pathname.match(/fullcpgrid/i)) setInterval(() => this.burst(false), 1000)
50 |
51 | Observable.fromEvent(window, "resize").subscribe(() => this.onResize())
52 | }
53 |
54 | burst(fromMouse:boolean = false)
55 | {
56 | for(let i = 0; i < 5; i++) this.createRandomSqwig(fromMouse);
57 | }
58 |
59 | createSqwigFromMouse(position:Position)
60 | {
61 | let sections:number = 4;
62 | if(this.lastMousePosition)
63 | {
64 | let newDirection:Position = {x: 0, y: 0};
65 | let xAmount = Math.abs(this.lastMousePosition.x - position.x);
66 | let yAmount = Math.abs(this.lastMousePosition.y - position.y);
67 |
68 | if(xAmount > yAmount)
69 | {
70 | newDirection.x = this.lastMousePosition.x - position.x < 0 ? 1 : -1;
71 | sections += Math.round(xAmount/4)
72 | }
73 | else
74 | {
75 | newDirection.y = this.lastMousePosition.y - position.y < 0 ? 1 : -1;
76 | sections += Math.round(yAmount/4)
77 | }
78 | this.direction = newDirection;
79 | }
80 |
81 | if(this.direction)
82 | {
83 | let settings:SquiggleSettings = {
84 | x: this.lastMousePosition.x,
85 | y: this.lastMousePosition.y,
86 | directionX: this.direction.x,
87 | directionY: this.direction.y,
88 | sections: sections > 20 ? 20 : sections
89 | }
90 | let newSqwig = new Squiggle(this.svg, settings, 10 + Math.random() * (sections * 1.5));
91 | this.squiggles.push(newSqwig);
92 | }
93 |
94 | this.lastMousePosition = position;
95 | }
96 |
97 | createRandomSqwig(fromMouse:boolean = false)
98 | {
99 | let dx = Math.random();
100 | if(dx > 0.5) dx = dx > 0.75 ? 1 : -1;
101 | else dx = 0;
102 | let dy= 0;
103 | if(dx == 0) dx = Math.random() > 0.5 ? 1 : -1;
104 |
105 | let settings:SquiggleSettings = {
106 | x: fromMouse ? this.lastMousePosition.x : this.width / 2, // Math.round(Math.random() * (this.width / this.grid)) * this.grid,
107 | y: fromMouse ? this.lastMousePosition.y : this.height / 2, //Math.round(Math.random() * (this.height / this.grid)) * this.grid,
108 | directionX: dx,
109 | directionY: dy,
110 | sections: 5 + Math.round(Math.random() * 15)
111 | }
112 | let newSqwig = new Squiggle(this.svg, settings, this.grid/2 + Math.random() * this.grid/2);
113 | this.squiggles.push(newSqwig);
114 | }
115 |
116 | onResize()
117 | {
118 | this.width = this.container.offsetWidth;
119 | this.height = this.container.offsetHeight;
120 |
121 | this.svg.setAttribute('width', String(this.width));
122 | this.svg.setAttribute('height', String(this.height));
123 | }
124 |
125 | tick()
126 | {
127 | // if(this.direction && this.squiggles.length < this.lineCount)
128 | // {
129 |
130 | // }
131 |
132 | let step = this.squiggles.length - 1;
133 |
134 | while(step >= 0)
135 | {
136 | if(this.squiggles[step].state != SquiggleState.ended)
137 | {
138 | this.squiggles[step].update();
139 |
140 | }
141 | else
142 | {
143 | this.squiggles[step] = null;
144 | this.squiggles.splice(step, 1);
145 | }
146 |
147 | --step;
148 | }
149 |
150 | requestAnimationFrame(() => this.tick());
151 | }
152 | }
--------------------------------------------------------------------------------
/src/app/input.ts:
--------------------------------------------------------------------------------
1 | import { Observable } from "rxjs";
2 | import { Position } from "./Position";
3 |
4 | // code form https://codepen.io/HunorMarton/post/handling-complex-mouse-and-touch-events-with-rxjs
5 |
6 | export class Input
7 | {
8 | private mouseDowns:Observable;
9 | private mouseMoves:Observable;
10 | private mouseUps:Observable;
11 |
12 | private touchStarts:Observable;
13 | private touchMoves:Observable;
14 | private touchEnds:Observable;
15 |
16 | public starts:Observable;
17 | public moves:Observable;
18 | public ends:Observable;
19 |
20 | constructor(element:HTMLElement)
21 | {
22 | this.mouseDowns = Observable.fromEvent(element, "mousedown").map(this.mouseEventToCoordinate);
23 | this.mouseMoves = Observable.fromEvent(window, "mousemove").map(this.mouseEventToCoordinate);
24 | this.mouseUps = Observable.fromEvent(window, "mouseup").map(this.mouseEventToCoordinate);
25 |
26 | this.touchStarts = Observable.fromEvent(element, "touchstart").map(this.touchEventToCoordinate);
27 | this.touchMoves = Observable.fromEvent(element, "touchmove").map(this.touchEventToCoordinate);
28 | this.touchEnds = Observable.fromEvent(window, "touchend").map(this.touchEventToCoordinate);
29 |
30 | this.starts = this.mouseDowns.merge(this.touchStarts);
31 | this.moves = this.mouseMoves.merge(this.touchMoves);
32 | this.ends = this.mouseUps.merge(this.touchEnds);
33 | }
34 |
35 | private mouseEventToCoordinate = (mouseEvent:MouseEvent) =>
36 | {
37 | mouseEvent.preventDefault();
38 | return {
39 | x: mouseEvent.clientX,
40 | y: mouseEvent.clientY
41 | };
42 | };
43 |
44 | private touchEventToCoordinate = (touchEvent:TouchEvent) =>
45 | {
46 | touchEvent.preventDefault();
47 | return {
48 | x: touchEvent.changedTouches[0].clientX,
49 | y: touchEvent.changedTouches[0].clientY
50 | };
51 | };
52 | }
--------------------------------------------------------------------------------
/src/app/squiggles/Settings.ts:
--------------------------------------------------------------------------------
1 | export interface SquiggleSettings
2 | {
3 | x: number;
4 | y: number;
5 | directionX: number;
6 | directionY: number;
7 | length?: number;
8 | sections: number;
9 | width?: number;
10 | chunkLength?: number;
11 | color?: string;
12 | progress?: number;
13 | opacity?: number;
14 | }
--------------------------------------------------------------------------------
/src/app/squiggles/State.ts:
--------------------------------------------------------------------------------
1 | export enum SquiggleState
2 | {
3 | ready,
4 | animating,
5 | ended
6 | }
--------------------------------------------------------------------------------
/src/app/squiggles/squiggle.ts:
--------------------------------------------------------------------------------
1 | import { SquiggleSettings } from "./Settings";
2 | import { SquiggleState } from "./State";
3 | import { TweenLite, Power1 } from "gsap";
4 |
5 | interface SquiggleSet
6 | {
7 | path: SVGPathElement;
8 | settings: SquiggleSettings;
9 | }
10 |
11 | export class Squiggle
12 | {
13 | private grid:number;
14 | private stage:HTMLElement;
15 | private sqwig:SVGPathElement;
16 | private sqwigs: SquiggleSet[] = [];
17 | private settings:SquiggleSettings;
18 | public state:SquiggleState = SquiggleState.ready;
19 |
20 | constructor(stage:HTMLElement, settings:SquiggleSettings, grid:number)
21 | {
22 | this.grid = grid;
23 | this.stage = stage;
24 |
25 | settings.width = 0;
26 | settings.opacity = 1;
27 |
28 | this.state = SquiggleState.animating;
29 | let path = this.createLine(settings);
30 | let sqwigCount:number = 3;
31 | for(let i = 0; i < sqwigCount; i++)
32 | {
33 | this.createSqwig(i, sqwigCount, path, JSON.parse(JSON.stringify(settings)) as SquiggleSettings, i == sqwigCount - 1)
34 | }
35 | }
36 |
37 | createSqwig(index:number, total:number, path:string, settings:SquiggleSettings, forceWhite:boolean)
38 | {
39 | let sqwig = document.createElementNS("http://www.w3.org/2000/svg", 'path')
40 | sqwig.setAttribute('d', path)
41 | sqwig.style.fill = 'none';
42 | sqwig.style.stroke = forceWhite ? '#303030' : this.getColor();
43 | sqwig.style.strokeLinecap = "round"
44 |
45 | settings.length = sqwig.getTotalLength();
46 | settings.chunkLength = settings.length / 6; //(settings.sections * 2) + (Math.random() * 40);
47 | settings.progress = settings.chunkLength;
48 |
49 | sqwig.style.strokeDasharray= `${settings.chunkLength}, ${settings.length + settings.chunkLength}`
50 | sqwig.style.strokeDashoffset = `${settings.progress}`
51 |
52 | this.stage.appendChild(sqwig);
53 |
54 | this.sqwigs.unshift({path: sqwig, settings: settings});
55 |
56 | TweenLite.to(settings, settings.sections * 0.1, {
57 | progress: - settings.length,
58 | width: settings.sections * 0.9,
59 | ease: Power1.easeOut,
60 | delay: index * (settings.sections * 0.01),
61 | onComplete: () =>
62 | {
63 | if(index = total - 1) this.state = SquiggleState.ended;
64 | sqwig.remove();
65 | }
66 | })
67 | }
68 |
69 | public update()
70 | {
71 | this.sqwigs.map((set: SquiggleSet) =>
72 | {
73 | set.path.style.strokeDashoffset = `${set.settings.progress}`;
74 | set.path.style.strokeWidth = `${set.settings.width}px`;
75 | set.path.style.opacity = `${set.settings.opacity}`;
76 | })
77 |
78 | }
79 |
80 | private createLine(settings:SquiggleSettings):string
81 | {
82 | let x = settings.x;
83 | let y = settings.y;
84 | let dx = settings.directionX;
85 | let dy = settings.directionY;
86 | let path:string[] = [
87 | 'M',
88 | '' + x,
89 | '' + y,
90 | "Q"
91 | ]
92 |
93 | let steps = settings.sections;
94 | let step = 0;
95 | let getNewDirection = (direction: string, goAnywhere:boolean) =>
96 | {
97 | if(!goAnywhere && settings['direction' + direction.toUpperCase()] != 0) return settings['direction' + direction.toUpperCase()];
98 | return Math.random() < 0.5 ? -1 : 1;
99 | }
100 |
101 | while(step < steps * 2)
102 | {
103 | step++;
104 | x += (dx * (step/ 30)) * this.grid;
105 | y += (dy * (step/ 30)) * this.grid;
106 | if(step != 1) path.push(',');
107 | path.push('' + x);
108 | path.push('' + y);
109 |
110 | if(step % 2 != 0)
111 | {
112 | dx = dx == 0 ? getNewDirection('x', step > 8) : 0;
113 | dy = dy == 0 ? getNewDirection('y', step > 8) : 0;
114 | }
115 | }
116 |
117 | return path.join(' ');
118 | }
119 |
120 | private getColor():string
121 | {
122 | let offset = Math.round(Math.random() * 100)
123 | var r = Math.sin(0.3 * offset) * 100 + 155;
124 | var g = Math.sin(0.3 * offset + 2) * 100 + 155;
125 | var b = Math.sin(0.3 * offset + 4) * 100 + 155;
126 | return "#" + this.componentToHex(r) + this.componentToHex(g) + this.componentToHex(b);
127 | }
128 |
129 | private componentToHex(c:number)
130 | {
131 | var hex = Math.round(c).toString(16);
132 | return hex.length == 1 ? "0" + hex : hex;
133 | }
134 | }
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | SVG Squiggles
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import './styles.scss';
2 | import { App } from "./app/app";
3 |
4 | let container = document.getElementById('app');
5 | let app = new App(container);
--------------------------------------------------------------------------------
/src/package.ts:
--------------------------------------------------------------------------------
1 | // declare variables defined by webpack from package.json
2 |
3 | declare var VERSION:string;
4 |
5 | interface Package
6 | {
7 | version: string
8 | }
9 |
10 | export function Pkg():Package
11 | {
12 | return { version: VERSION }
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/src/styles.scss:
--------------------------------------------------------------------------------
1 | html, body
2 | {
3 | width: 100%;
4 | height: 100%;
5 | overflow: hidden;
6 | margin: 0;
7 | padding: 0;
8 | user-select: none;
9 | color: #111;
10 | }
11 |
12 | body
13 | {
14 | background-color: #303030;
15 | }
16 |
17 | #app
18 | {
19 | width: 100%;
20 | height: 100%;
21 | }
--------------------------------------------------------------------------------
/src/vendor.ts:
--------------------------------------------------------------------------------
1 | //import "gsap";
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "lib": [
6 | "es2016",
7 | "dom"
8 | ],
9 | "moduleResolution": "node",
10 | "sourceMap": true,
11 | "emitDecoratorMetadata": true,
12 | "experimentalDecorators": true,
13 | "removeComments": false,
14 | "noImplicitAny": true,
15 | "suppressImplicitAnyIndexErrors": true
16 | }
17 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./config/webpack.dev.js');
--------------------------------------------------------------------------------