From 9a4b216fd9b6254ba13125b5cd1ac349e7bb1598 Mon Sep 17 00:00:00 2001 From: Chris Schuhmacher Date: Tue, 22 Oct 2019 09:16:14 -0700 Subject: [PATCH 1/3] Add typescript config and dependencies --- README.md | 29 ++++++ sample-react-redux-tutorial/package.json | 7 ++ sample-react-redux-tutorial/tsconfig.json | 10 ++ sample-react-redux-tutorial/yarn.lock | 118 +++++++++++++++++++++- 4 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 sample-react-redux-tutorial/tsconfig.json diff --git a/README.md b/README.md index 8017a87..8a41429 100644 --- a/README.md +++ b/README.md @@ -557,6 +557,35 @@ ConnectedRelapseButton.propTypes = { } ``` +## Hey What About Typescript? + +Typescript Indeed... but what is it? Typescript is a superset of JavaScript that provides optional static typing, classes and interfaces. It helps as you develop by adding a richer environment to your IDE for spotting typos and coding errors. + +First, let's add the dependencies. + +`$ yarn add @types/react @types/react-dom typescript ts-loader source-map-loader` + +Next let's add a **TypeScript** configuration file. + +**tsconfig.json** + +``` +{ + "compilerOptions": { + "outDir": "./dist/", + "sourceMap": true, + "noImplicitAny": true, + "module": "commonjs", + "target": "es6", + "jsx": "react" + } +} +``` + + + + + ## Finishing Up So, there it is... our sobriety/relapse tracker. I hope this tutorial didn't drive you to drink, but if it did feel safe in knowing that with this app, you're in control. diff --git a/sample-react-redux-tutorial/package.json b/sample-react-redux-tutorial/package.json index 159e3a1..1d462d3 100644 --- a/sample-react-redux-tutorial/package.json +++ b/sample-react-redux-tutorial/package.json @@ -7,6 +7,8 @@ "@babel/core": "^7.6.0", "@babel/preset-env": "^7.6.0", "@babel/preset-react": "^7.0.0", + "@types/react": "^16.9.9", + "@types/react-dom": "^16.9.2", "babel-loader": "^8.0.6", "html-loader": "^0.5.5", "html-webpack-plugin": "^3.2.0", @@ -25,5 +27,10 @@ "scripts": { "build": "webpack --mode production", "start": "webpack-dev-server --mode development" + }, + "dependencies": { + "source-map-loader": "^0.2.4", + "ts-loader": "^6.2.0", + "typescript": "^3.6.4" } } diff --git a/sample-react-redux-tutorial/tsconfig.json b/sample-react-redux-tutorial/tsconfig.json new file mode 100644 index 0000000..d99f9b0 --- /dev/null +++ b/sample-react-redux-tutorial/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "outDir": "./dist/", + "sourceMap": true, + "noImplicitAny": true, + "module": "commonjs", + "target": "es6", + "jsx": "react" + } +} diff --git a/sample-react-redux-tutorial/yarn.lock b/sample-react-redux-tutorial/yarn.lock index 81ae136..c84b23e 100644 --- a/sample-react-redux-tutorial/yarn.lock +++ b/sample-react-redux-tutorial/yarn.lock @@ -727,6 +727,26 @@ resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/@types/node/-/node-12.7.4.tgz#64db61e0359eb5a8d99b55e05c729f130a678b04" integrity sha1-ZNth4DWetajZm1XgXHKfEwpniwQ= +"@types/prop-types@*": + version "15.7.3" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha1-KrDV2i5YFflLC51LldHl8kOrLKc= + +"@types/react-dom@^16.9.2": + version "16.9.2" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/@types/react-dom/-/react-dom-16.9.2.tgz#90f9e6c161850be1feb31d2f448121be2a4f3b47" + integrity sha1-kPnmwWGFC+H+sx0vRIEhvipPO0c= + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^16.9.9": + version "16.9.9" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/@types/react/-/react-16.9.9.tgz#a62c6f40f04bc7681be5e20975503a64fe783c3a" + integrity sha1-pixvQPBLx2gb5eIJdVA6ZP54PDo= + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + "@webassemblyjs/ast@1.8.5": version "1.8.5" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" @@ -1058,6 +1078,13 @@ async@^1.5.2: resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= +async@^2.5.0: + version "2.6.3" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8= + dependencies: + lodash "^4.17.14" + atob@^2.1.1: version "2.1.2" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -1190,6 +1217,13 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" +braces@^3.0.1: + version "3.0.2" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha1-NFThpGLujVmeI23zNs2epPiv4Qc= + dependencies: + fill-range "^7.0.1" + brorand@^1.0.1: version "1.1.0" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -1356,7 +1390,7 @@ caniuse-lite@^1.0.30000989: resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz#b9193e293ccf7e4426c5245134b8f2a56c0ac4b9" integrity sha1-uRk+KTzPfkQmxSRRNLjypWwKxLk= -chalk@2.4.2, chalk@^2.0.0: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.3.0: version "2.4.2" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ= @@ -1679,6 +1713,11 @@ css-what@2.1: resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" integrity sha1-ptdgRXM2X+dGhsPzEcVlE9iChfI= +csstype@^2.2.0: + version "2.6.7" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5" + integrity sha1-ILACTCC2cY9O2jhTofWhzOf15KU= + cyclist@^1.0.1: version "1.0.1" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" @@ -1971,6 +2010,15 @@ enhanced-resolve@4.1.0, enhanced-resolve@^4.1.0: memory-fs "^0.4.0" tapable "^1.0.0" +enhanced-resolve@^4.0.0: + version "4.1.1" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" + integrity sha1-KTfiuAZs0P584JkKmPDXGjUYn2Y= + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + entities@^1.1.1: version "1.1.2" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" @@ -2233,6 +2281,13 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha1-GRmmp8df44ssfHflGYU12prN2kA= + dependencies: + to-regex-range "^5.0.1" + finalhandler@~1.1.2: version "1.1.2" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" @@ -2940,6 +2995,11 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^7.0.0: + version "7.0.0" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss= + is-path-cwd@^2.0.0: version "2.2.0" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" @@ -3139,7 +3199,7 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.3: +lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.3: version "4.17.15" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg= @@ -3231,6 +3291,14 @@ memory-fs@^0.4.0, memory-fs@^0.4.1: errno "^0.1.3" readable-stream "^2.0.1" +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha1-MkwBKIuIZSlm0WHbd4OHIIRajjw= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -3260,6 +3328,14 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.0: + version "4.0.2" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha1-T8sJmb+fvC/L3SEvbWKbmlbDklk= + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -3866,6 +3942,11 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +picomatch@^2.0.5: + version "2.0.7" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" + integrity sha1-UUFp2MfNC9vuzIomCeNKcWPeafY= + pify@^2.0.0: version "2.3.0" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -4410,7 +4491,7 @@ semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha1-qVT5Ma66UI0we78Gnv8MAclhFvc= -semver@^6.3.0: +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0= @@ -4572,6 +4653,14 @@ source-list-map@^2.0.0: resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ= +source-map-loader@^0.2.4: + version "0.2.4" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/source-map-loader/-/source-map-loader-0.2.4.tgz#c18b0dc6e23bf66f6792437557c569a11e072271" + integrity sha1-wYsNxuI79m9nkkN1V8VpoR4HInE= + dependencies: + async "^2.5.0" + loader-utils "^1.1.0" + source-map-resolve@^0.5.0: version "0.5.2" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" @@ -4886,6 +4975,13 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ= + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" @@ -4911,6 +5007,17 @@ trim-right@^1.0.1: resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= +ts-loader@^6.2.0: + version "6.2.0" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/ts-loader/-/ts-loader-6.2.0.tgz#52d3993ecbc5474c1513242388e1049da0fce880" + integrity sha1-UtOZPsvFR0wVEyQjiOEEnaD86IA= + dependencies: + chalk "^2.3.0" + enhanced-resolve "^4.0.0" + loader-utils "^1.0.2" + micromatch "^4.0.0" + semver "^6.0.0" + tslib@^1.9.0: version "1.10.0" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" @@ -4934,6 +5041,11 @@ typedarray@^0.0.6: resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript@^3.6.4: + version "3.6.4" + resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/typescript/-/typescript-3.6.4.tgz#b18752bb3792bc1a0281335f7f6ebf1bbfc5b91d" + integrity sha1-sYdSuzeSvBoCgTNff26/G7/FuR0= + uglify-js@3.4.x: version "3.4.10" resolved "https://artifactory.wikia-inc.com:443/artifactory/api/npm/wikia-npm/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" From 08f5cba4d53b886768dc2e1433f7126b255f21ba Mon Sep 17 00:00:00 2001 From: Chris Schuhmacher Date: Tue, 22 Oct 2019 09:50:16 -0700 Subject: [PATCH 2/3] Changed DatePicker to .tsx --- .../src/components/App.jsx | 2 +- .../{DatePicker.jsx => DatePicker.tsx} | 16 ++++++++-------- sample-react-redux-tutorial/webpack.config.js | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 9 deletions(-) rename sample-react-redux-tutorial/src/components/{DatePicker.jsx => DatePicker.tsx} (67%) diff --git a/sample-react-redux-tutorial/src/components/App.jsx b/sample-react-redux-tutorial/src/components/App.jsx index fc7802f..e8fcfe9 100644 --- a/sample-react-redux-tutorial/src/components/App.jsx +++ b/sample-react-redux-tutorial/src/components/App.jsx @@ -1,6 +1,6 @@ import React from 'react' -import DatePicker from './DatePicker.jsx'; +import DatePicker from './DatePicker.tsx'; import RelapseList from './RelapseList.jsx'; import RelapseButton from './RelapseButton.jsx'; import TimeDisplay from './TimeDisplay.jsx'; diff --git a/sample-react-redux-tutorial/src/components/DatePicker.jsx b/sample-react-redux-tutorial/src/components/DatePicker.tsx similarity index 67% rename from sample-react-redux-tutorial/src/components/DatePicker.jsx rename to sample-react-redux-tutorial/src/components/DatePicker.tsx index b9b930f..c92c1bd 100644 --- a/sample-react-redux-tutorial/src/components/DatePicker.jsx +++ b/sample-react-redux-tutorial/src/components/DatePicker.tsx @@ -3,20 +3,24 @@ import React from 'react'; import { connect } from 'react-redux'; import { updateTimeSober } from '../actions/index'; -function mapDispatchToProps(dispatch) { +function mapDispatchToProps(dispatch: any) { return { - dispatchUpdateSobrietyDate: timeSober => dispatch(updateTimeSober(timeSober)), + dispatchUpdateSobrietyDate: (timeSober: string) => dispatch(updateTimeSober(timeSober)), }; }; -class ConnectedDatePicker extends React.Component { +interface DatePickerProps { + dispatchUpdateSobrietyDate: any; +}; + +class ConnectedDatePicker extends React.Component { constructor() { super(); this.handleChange = this.handleChange.bind(this); } - handleChange(el) { + handleChange(el: any) { el.preventDefault(); const date = new Date(el.target.value).toUTCString(); this.props.dispatchUpdateSobrietyDate(date); @@ -27,10 +31,6 @@ class ConnectedDatePicker extends React.Component { } }; -ConnectedDatePicker.propTypes = { - dispatchUpdateSobrietyDate: PropTypes.func.isRequired, -}; - const DatePicker = connect(null, mapDispatchToProps)(ConnectedDatePicker); export default DatePicker; diff --git a/sample-react-redux-tutorial/webpack.config.js b/sample-react-redux-tutorial/webpack.config.js index 604a330..23117c6 100644 --- a/sample-react-redux-tutorial/webpack.config.js +++ b/sample-react-redux-tutorial/webpack.config.js @@ -11,6 +11,20 @@ module.exports = { loader: "babel-loader" } }, + { + test: /\.ts(x?)$/, + exclude: /node_modules/, + use: [ + { + loader: "ts-loader" + } + ] + }, + { + enforce: "pre", + test: /\.js$/, + loader: "source-map-loader" + }, { test: /\.html$/, use: [ @@ -21,6 +35,10 @@ module.exports = { } ] }, + externals: { + "react": "React", + "react-dom": "ReactDOM" + }, plugins: [ new HtmlWebPackPlugin({ template: "./src/index.html", From f4b9a53cdd46bed983e86a3ea9f8c2b94301aa2f Mon Sep 17 00:00:00 2001 From: Chris Schuhmacher Date: Tue, 22 Oct 2019 09:52:52 -0700 Subject: [PATCH 3/3] Update README typescript/webpack config --- README.md | 56 +++++++++++++++++++ sample-react-redux-tutorial/webpack.config.js | 3 + 2 files changed, 59 insertions(+) diff --git a/README.md b/README.md index 8a41429..ef6fde3 100644 --- a/README.md +++ b/README.md @@ -582,6 +582,62 @@ Next let's add a **TypeScript** configuration file. } ``` +And update our webpack config. + +``` +const HtmlWebPackPlugin = require("html-webpack-plugin"); + +module.exports = { + entry: "./src/index.js", + + devtool: "source-map", + + module: { + rules: [ + { + test: /\.(js|jsx)$/, + exclude: /node_modules/, + use: { + loader: "babel-loader" + } + }, + { + test: /\.ts(x?)$/, + exclude: /node_modules/, + use: [ + { + loader: "ts-loader" + } + ] + }, + { + enforce: "pre", + test: /\.js$/, + loader: "source-map-loader" + }, + { + test: /\.html$/, + use: [ + { + loader: "html-loader" + } + ] + } + ] + }, + externals: { + "react": "React", + "react-dom": "ReactDOM" + }, + plugins: [ + new HtmlWebPackPlugin({ + template: "./src/index.html", + filename: "./index.html" + }) + ] +}; +``` + diff --git a/sample-react-redux-tutorial/webpack.config.js b/sample-react-redux-tutorial/webpack.config.js index 23117c6..c817315 100644 --- a/sample-react-redux-tutorial/webpack.config.js +++ b/sample-react-redux-tutorial/webpack.config.js @@ -2,6 +2,9 @@ const HtmlWebPackPlugin = require("html-webpack-plugin"); module.exports = { entry: "./src/index.js", + + devtool: "source-map", + module: { rules: [ {