diff --git a/.babelrc b/.babelrc index 2b7bafa..49f21d0 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,11 @@ { - "presets": ["@babel/preset-env", "@babel/preset-react"] + "presets": [ + "@babel/env", + "@babel/react", + ["@babel/typescript", { + "isTSX": true, + "allExtensions": true + }] + ], + "plugins": ["@babel/proposal-class-properties", "@babel/proposal-object-rest-spread"] } diff --git a/.eslintrc b/.eslintrc index 683e8c7..87d0b78 100644 --- a/.eslintrc +++ b/.eslintrc @@ -10,6 +10,14 @@ "rules": { "prettier/prettier": ["error"], "import/no-extraneous-dependencies": 0, - "react/jsx-filename-extension": 0 + "react/jsx-filename-extension": 0, + "react/prop-types": 0 + }, + "settings": { + "import/resolver": { + "node": { + "extensions": [".js", ".jsx", ".ts", ".tsx"] + } + } } } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..33017e7 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "eslint.validate": [ + "javascript", + "javascriptreact", + { "language": "typescript", "autoFix": true }, + { "language": "typescriptreact", "autoFix": true } + ], +} \ No newline at end of file diff --git a/build-utils/addons/webpack.bundleanalyze.js b/build-utils/addons/webpack.bundleanalyze.ts similarity index 74% rename from build-utils/addons/webpack.bundleanalyze.js rename to build-utils/addons/webpack.bundleanalyze.ts index bab7698..bbb4630 100644 --- a/build-utils/addons/webpack.bundleanalyze.js +++ b/build-utils/addons/webpack.bundleanalyze.ts @@ -1,11 +1,12 @@ -const WebpackBundleAnalyzer = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; +const WebpackBundleAnalyzer = require('webpack-bundle-analyzer') + .BundleAnalyzerPlugin; module.exports = { plugins: [ new WebpackBundleAnalyzer({ analyzerMode: 'static', reportFilename: './report.html', - openAnalyzer: false - }) - ] -}; \ No newline at end of file + openAnalyzer: false, + }), + ], +}; diff --git a/build-utils/addons/webpack.bundlevisualizer.js b/build-utils/addons/webpack.bundlevisualizer.ts similarity index 65% rename from build-utils/addons/webpack.bundlevisualizer.js rename to build-utils/addons/webpack.bundlevisualizer.ts index 222e587..4ece17a 100644 --- a/build-utils/addons/webpack.bundlevisualizer.js +++ b/build-utils/addons/webpack.bundlevisualizer.ts @@ -1,7 +1,5 @@ const Visualizer = require('webpack-visualizer-plugin'); module.exports = { - plugins: [ - new Visualizer() - ] -}; \ No newline at end of file + plugins: [new Visualizer()], +}; diff --git a/build-utils/webpack.common.js b/build-utils/webpack.common.ts similarity index 84% rename from build-utils/webpack.common.js rename to build-utils/webpack.common.ts index a0f56a3..cc28131 100644 --- a/build-utils/webpack.common.js +++ b/build-utils/webpack.common.ts @@ -3,18 +3,18 @@ const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { - entry: './src/index.js', + entry: './src/index', module: { rules: [ { - test: /\.(js|jsx)$/, + test: /\.(ts|tsx|js|jsx)$/, exclude: /node_modules/, use: ['babel-loader', 'eslint-loader'], }, ], }, resolve: { - extensions: ['*', '.js', '.jsx'], + extensions: ['*', '.ts', '.tsx', '.js', '.jsx'], }, plugins: [ new CleanWebpackPlugin(), diff --git a/build-utils/webpack.config.js b/build-utils/webpack.config.ts similarity index 71% rename from build-utils/webpack.config.js rename to build-utils/webpack.config.ts index 8629ce8..7ce056a 100644 --- a/build-utils/webpack.config.js +++ b/build-utils/webpack.config.ts @@ -3,7 +3,7 @@ const webpackMerge = require('webpack-merge'); -const commonConfig = require('./webpack.common.js'); +const commonConfig = require('./webpack.common.ts'); const getAddons = addonsArgs => { const addons = Array.isArray(addonsArgs) @@ -12,11 +12,11 @@ const getAddons = addonsArgs => { return addons .filter(Boolean) - .map(name => require(`./addons/webpack.${name}.js`)); + .map(name => require(`./addons/webpack.${name}.ts`)); }; module.exports = ({ env, addon }) => { - const envConfig = require(`./webpack.${env}.js`); + const envConfig = require(`./webpack.${env}.ts`); return webpackMerge(commonConfig, envConfig, ...getAddons(addon)); }; diff --git a/build-utils/webpack.dev.js b/build-utils/webpack.dev.ts similarity index 100% rename from build-utils/webpack.dev.js rename to build-utils/webpack.dev.ts diff --git a/build-utils/webpack.prod.js b/build-utils/webpack.prod.ts similarity index 100% rename from build-utils/webpack.prod.js rename to build-utils/webpack.prod.ts diff --git a/package-lock.json b/package-lock.json index 2f2ca23..935e337 100644 --- a/package-lock.json +++ b/package-lock.json @@ -127,6 +127,20 @@ "@babel/types": "^7.4.4" } }, + "@babel/helper-create-class-features-plugin": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.6.0.tgz", + "integrity": "sha512-O1QWBko4fzGju6VoVvrZg0RROCVifcLxiApnGP3OWfWzvxRZFCoBD81K5ur5e3bVY2Vf/5rIJm8cqPKn8HUJng==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-member-expression-to-functions": "^7.5.5", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5", + "@babel/helper-split-export-declaration": "^7.4.4" + } + }, "@babel/helper-define-map": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", @@ -352,6 +366,16 @@ "@babel/plugin-syntax-async-generators": "^7.2.0" } }, + "@babel/plugin-proposal-class-properties": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz", + "integrity": "sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.5.5", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/plugin-proposal-dynamic-import": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", @@ -457,6 +481,15 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-syntax-typescript": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz", + "integrity": "sha512-dGwbSMA1YhVS8+31CnPR7LB4pcbrzcV99wQzby4uAfrkZPYZlQ7ImwdpzLqi6Z6IL02b8IAL379CaMwo0x5Lag==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/plugin-transform-arrow-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", @@ -802,6 +835,17 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-transform-typescript": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.6.3.tgz", + "integrity": "sha512-aiWINBrPMSC3xTXRNM/dfmyYuPNKY/aexYqBgh0HBI5Y+WO5oRAqW/oROYeYHrF4Zw12r9rK4fMk/ZlAmqx/FQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.6.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-typescript": "^7.2.0" + } + }, "@babel/plugin-transform-unicode-regex": { "version": "7.6.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz", @@ -884,6 +928,16 @@ "@babel/plugin-transform-react-jsx-source": "^7.0.0" } }, + "@babel/preset-typescript": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.6.0.tgz", + "integrity": "sha512-4xKw3tTcCm0qApyT6PqM9qniseCE79xGHiUnNdKGdxNsGUc2X7WwZybqIpnTmoukg3nhPceI5KPNzNqLNeIJww==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.6.0" + } + }, "@babel/runtime": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz", @@ -998,6 +1052,31 @@ "integrity": "sha512-b8bbUOTwzIY3V5vDTY1fIJ+ePKDUBqt2hC2woVGotdQQhG/2Sh62HOKHrT7ab+VerXAcPyAiTEipPu/FsreUtg==", "dev": true }, + "@types/prop-types": { + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==", + "dev": true + }, + "@types/react": { + "version": "16.9.9", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.9.tgz", + "integrity": "sha512-L+AudFJkDukk+ukInYvpoAPyJK5q1GanFOINOJnM0w6tUgITuWvJ4jyoBPFL7z4/L8hGLd+K/6xR5uUjXu0vVg==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "@types/react-dom": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.2.tgz", + "integrity": "sha512-hgPbBoI1aTSTvZwo8HYw35UaTldW6n2ETLvHAcfcg1FaOuBV3olmyCe5eMpx2WybWMBPv0MdU2t5GOcQhP+3zA==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/tapable": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.4.tgz", @@ -1042,6 +1121,12 @@ } } }, + "@types/webpack-env": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.14.1.tgz", + "integrity": "sha512-0Ki9jAAhKDSuLDXOIMADg54Hu60SuBTEsWaJGGy5cV+SSUQ63J2a+RrYYGrErzz39fXzTibhKrAQJAb8M7PNcA==", + "dev": true + }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -2486,6 +2571,12 @@ "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", "dev": true }, + "csstype": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.7.tgz", + "integrity": "sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ==", + "dev": true + }, "cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", @@ -5561,9 +5652,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, "loglevel": { diff --git a/package.json b/package.json index 3f224cc..0f5a0ca 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "description": "", "main": "index.js", "scripts": { - "start": "webpack-dev-server --config build-utils/webpack.config.js --env.env=dev", - "build": "webpack --config build-utils/webpack.config.js --env.env=prod", + "start": "webpack-dev-server --config build-utils/webpack.config.ts --env.env=dev", + "build": "webpack --config build-utils/webpack.config.ts --env.env=prod", "build:analyze": "npm run build -- --env.addon=bundleanalyze --env.addon=bundlevisualizer", "test": "echo \"Error: no test specified\" && exit 0" }, @@ -14,8 +14,14 @@ "license": "MIT", "devDependencies": { "@babel/core": "^7.6.4", + "@babel/plugin-proposal-class-properties": "^7.5.5", + "@babel/plugin-proposal-object-rest-spread": "^7.6.2", "@babel/preset-env": "^7.6.3", "@babel/preset-react": "^7.6.3", + "@babel/preset-typescript": "^7.6.0", + "@types/react": "^16.9.9", + "@types/react-dom": "^16.9.2", + "@types/webpack-env": "^1.14.1", "babel-eslint": "^10.0.3", "babel-loader": "^8.0.6", "clean-webpack-plugin": "^3.0.0", @@ -39,7 +45,6 @@ "webpack-visualizer-plugin": "^0.1.11" }, "dependencies": { - "prop-types": "^15.7.2", "react": "^16.10.2", "react-dom": "^16.10.2" } diff --git a/src/App.js b/src/App.js deleted file mode 100644 index b121ab2..0000000 --- a/src/App.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const App = ({ title }) =>
{title}
; - -App.propTypes = { - title: PropTypes.string.isRequired, -}; - -export default App; diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..f37eb86 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,9 @@ +import React from 'react'; + +interface AppProps { + title: string; +} + +const App: React.FC = ({ title }) =>
{title}
; + +export default App; diff --git a/src/index.js b/src/index.tsx similarity index 100% rename from src/index.js rename to src/index.tsx