├── .babelrc ├── .env.development ├── .env.production ├── .env.staging ├── .eslintrc.js ├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── __mocks__ ├── fileMock.js └── styleMock.js ├── config ├── paths.js ├── webpack.common.js ├── webpack.dev.js ├── webpack.prod.js └── webpack.stag.js ├── package.json ├── postcss.config.js ├── public └── index.html ├── src ├── App.js ├── App.test.js ├── app.styles.scss ├── assets │ ├── altafino.svg │ └── icons │ │ └── favicon.png ├── index.js └── index.scss ├── tailwind.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ "@babel/preset-env", { 4 | "modules": "auto", 5 | "targets": { 6 | "browsers": [ 7 | "last 2 Chrome versions", 8 | "last 2 Firefox versions", 9 | "last 2 Safari versions", 10 | "last 2 iOS versions", 11 | "last 1 Android version", 12 | "last 1 ChromeAndroid version", 13 | "ie 11" 14 | ] 15 | } 16 | } ], 17 | ["@babel/preset-react", { 18 | "runtime": "automatic" 19 | }] 20 | ], 21 | "plugins": [ 22 | "@babel/plugin-proposal-class-properties", 23 | "@babel/plugin-transform-runtime" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | API_URL=http://localhost:8090/ -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | API_URL=https://api.production.com/ -------------------------------------------------------------------------------- /.env.staging: -------------------------------------------------------------------------------- 1 | API_URL=https://api.staging.com/ 2 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es6: true, 5 | node: true, 6 | }, 7 | parser: "babel-eslint", 8 | extends: [ 9 | "eslint:recommended", 10 | "plugin:react/recommended", 11 | "prettier", 12 | "prettier/react", 13 | ], 14 | parserOptions: { 15 | ecmaVersion: "2017", 16 | ecmaFeatures: { 17 | experimentalObjectRestSpread: true, 18 | jsx: true, 19 | }, 20 | sourceType: "module", 21 | }, 22 | plugins: ["babel", "react", "import", "prettier","react-hooks"], 23 | rules: { 24 | "import/no-duplicates": "error", 25 | "import/no-unresolved": "error", 26 | "import/named": "error", 27 | "prettier/prettier": "error", 28 | "react/no-typos": "error", 29 | "react/no-unused-state": "error", 30 | "react/jsx-no-bind": "error", 31 | "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks 32 | "react-hooks/exhaustive-deps": "warn", // Checks effect dependencies 33 | "react/jsx-uses-react": "off", 34 | "react/react-in-jsx-scope": "off", 35 | "array-callback-return": "error", 36 | "consistent-return": "error", 37 | "babel/no-invalid-this": "error", 38 | "no-unused-vars": ["error", { argsIgnorePattern: "^_" }], 39 | }, 40 | settings: { 41 | react: { 42 | pragma: "React", 43 | version: "detect", 44 | flowVersion: "0.63.1", 45 | }, 46 | }, 47 | }; 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | stats.json 4 | .DS_Store 5 | package-lock.json 6 | # jetbrains 7 | .idea -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | dist 4 | coverage 5 | .eslintrc.js 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "jsxSingleQuote": true, 4 | "semi": false, 5 | "bracketSpacing": true, 6 | "arrowParens": "always", 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Altafino Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # unmaintained 2 | I am not more maintain this project actively for different reasons. One is, that with Vite we have a nicer way to handle different aspects, other is time. 3 | But I check and can accept pull requests. 4 | 5 | ### Visit my [Job Board for React Jobs](https://reactjsjob.com) 6 | 7 | 8 | # react-webpack-6-tailwind-2 9 | 10 | React 17 Boilerplate with React 17, Webpack 6, Tailwind 2, HMR, using babel, Jest unit testing, sass, with a hot dev server and an optimized production build 11 | 12 | [Demo](https://dreamy-shirley-041c74.netlify.app/) 13 | 14 | Maintained by [Altafino - Full-Stack Go/JS Development](https://altafino.com) 15 | 16 | ## Last Changes (the newest first): 17 | 18 | - added full support for unit testing (with file mocks) using Jest 19 | - added SVGR as a webpack loader to import your SVG directly as a React Component. 20 | - added build-staging script. same as build but using .env.staging 21 | - added dotenv-webpack to handle process.env.VARS 22 | - added Prettier 23 | - added react-refresh-webpack-plugin for HMR 24 | 25 | ## Installation 26 | 27 | ``` 28 | git clone https://github.com/altafino/react-webpack-5-tailwind-2.git 29 | cd react-webpack-5-tailwind-2 30 | yarn / npm i 31 | ``` 32 | 33 | To use it for your own project the easiest way is to use the green Template Button on top right of this repo on Github. 34 | 35 | ## Usage 36 | 37 | ### Development server 38 | 39 | ```bash 40 | yarn start / npm start 41 | ``` 42 | 43 | You can view the development server at `localhost:3000`. 44 | (change port in ./config/webpack.dev.js) 45 | 46 | ### Unit Test 47 | 48 | ```bash 49 | yarn test / npm test 50 | ``` 51 | 52 | ### Production build 53 | 54 | ```bash 55 | yarn build / npm run build 56 | ``` 57 | 58 | ## Features 59 | 60 | - [React 17](https://reactjs.org/) 61 | - [Webpack 6](https://webpack.js.org/) 62 | - [Tailwind 2](https://tailwindcss.com) 63 | - [Jest 27](http://jestjs.io/) 64 | - [PostCss](https://postcss.org/) 65 | - [Babel](https://babeljs.io/) 66 | - [Sass](https://sass-lang.com/) 67 | - [Eslint](https://eslint.org/) 68 | - [Husky](https://github.com/typicode/husky) ( tks [@rubinj30](https://github.com/rubinj30) ) 69 | 70 | ## Dependencies 71 | 72 | ### webpack 73 | 74 | - [`webpack`](https://github.com/webpack/webpack) - Module and asset bundler. 75 | - [`webpack-cli`](https://github.com/webpack/webpack-cli) - Command line interface for webpack 76 | - [`webpack-dev-server`](https://github.com/webpack/webpack-dev-server) - Development server for webpack 77 | - [`webpack-merge`](https://github.com/survivejs/webpack-merge) - Simplify development/production configuration 78 | 79 | ### Babel 80 | 81 | - [`@babel/core`](https://www.npmjs.com/package/@babel/core) - Transpile ES6+ to backwards compatible JavaScript 82 | - [`@babel/plugin-proposal-class-properties`](https://babeljs.io/docs/en/babel-plugin-proposal-class-properties) - Use properties directly on a class (an example Babel config) 83 | - [`@babel/preset-env`](https://babeljs.io/docs/en/babel-preset-env) - Smart defaults for Babel 84 | 85 | ### Jest 86 | 87 | - [`jest`](https://jestjs.io/) - Delightful JavaScript Testing 88 | - [`@testing-library/jest-dom`](https://github.com/testing-library/jest-dom#readme) - Custom jest matchers to test the state of the DOM 89 | - [`@testing-library/react`](https://testing-library.com/docs/react-testing-library/intro/) - Simple and complete React DOM testing utilities 90 | - [`@testing-library/user-event`](https://github.com/testing-library/user-event#readme) - Fire events the same way the user does 91 | 92 | ### Loaders 93 | 94 | - [`babel-loader`](https://webpack.js.org/loaders/babel-loader/) - Transpile files with Babel and webpack 95 | - [`sass-loader`](https://webpack.js.org/loaders/sass-loader/) - Load SCSS and compile to CSS 96 | - [`node-sass`](https://github.com/sass/node-sass) - Node Sass 97 | - [`css-loader`](https://webpack.js.org/loaders/css-loader/) - Resolve CSS imports 98 | - [`postcss-loader`](https://webpack.js.org/loaders/postcss-loader/) - Loader to process CSS with PostCSS 99 | - [`style-loader`](https://webpack.js.org/loaders/style-loader/) - Inject CSS into the DOM 100 | 101 | ### Eslint 102 | 103 | - [`eslint-config-prettier`](https://www.npmjs.com/package/eslint-config-prettier) - Turns off all rules that are unnecessary or might conflict with Prettier. 104 | - [`eslint-import-resolver-alias`](https://www.npmjs.com/package/eslint-import-resolver-alias) - a simple Node behavior import resolution plugin for eslint-plugin-import, supporting module alias. 105 | - [`eslint-plugin-babel`](https://www.npmjs.com/package/eslint-plugin-babel) - an eslint rule plugin companion to babel-eslint. 106 | - [`eslint-plugin-import`](https://www.npmjs.com/package/eslint-plugin-import) - This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, and prevent issues with misspelling of file paths and import names. 107 | - [`eslint-plugin-prettier`](https://www.npmjs.com/package/eslint-plugin-prettier) - Runs prettier as an eslint rule. 108 | - [`eslint-plugin-react`](https://www.npmjs.com/package/eslint-plugin-react) - React specific linting rules for ESLint. 109 | - [`eslint-plugin-react-hooks`](https://github.com/facebook/react/tree/master/packages/eslint-plugin-react-hooks) - Enforces the Rules of React Hooks. 110 | 111 | ### Plugins 112 | 113 | - [`clean-webpack-plugin`](https://github.com/johnagan/clean-webpack-plugin) - Remove/clean build folders 114 | - [`copy-webpack-plugin`](https://github.com/webpack-contrib/copy-webpack-plugin) - Copy files to build directory 115 | - [`html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin) - Generate HTML files from template 116 | - [`mini-css-extract-plugin`](https://github.com/webpack-contrib/mini-css-extract-plugin) - Extract CSS into separate files 117 | - [`optimize-css-assets-webpack-plugin`](https://github.com/NMFR/optimize-css-assets-webpack-plugin) - Optimize and minimize CSS assets 118 | - [`terser-webpack-plugin`](https://github.com/webpack-contrib/terser-webpack-plugin) - Optimize and minimize JavaScript 119 | - [`react-refresh-webpack-plugin`](https://github.com/pmmmwh/react-refresh-webpack-plugin) - HMR using React Fast Refresh 120 | - [`dotenv-webpack`](https://github.com/mrsteele/dotenv-webpack) - Supports dotenv and other environment variables 121 | - [`@svgr/webpack`](https://github.com/mrsteele/dotenv-webpack) - SVGR can be used as a webpack loader, this way you can import your SVG directly as a React Component. 122 | - [`babel-jest`](https://www.npmjs.com/package/babel-jest) - Babel jest plugin for transforimg `.js` and `.jsx` files 123 | -------------------------------------------------------------------------------- /__mocks__/fileMock.js: -------------------------------------------------------------------------------- 1 | // __mocks__/fileMock.js 2 | module.exports = 'test-file-stub'; -------------------------------------------------------------------------------- /__mocks__/styleMock.js: -------------------------------------------------------------------------------- 1 | // __mocks__/styleMock.js 2 | module.exports = {}; -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | // Source files 5 | src: path.resolve(__dirname, '../src'), 6 | 7 | // Production build files 8 | build: path.resolve(__dirname, '../dist'), 9 | 10 | // Static files that get copied to build folder 11 | public: path.resolve(__dirname, '../public'), 12 | } 13 | -------------------------------------------------------------------------------- /config/webpack.common.js: -------------------------------------------------------------------------------- 1 | const paths = require('./paths') 2 | 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin') 4 | const CopyWebpackPlugin = require('copy-webpack-plugin') 5 | const HtmlWebpackPlugin = require('html-webpack-plugin') 6 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') // extract css to files 7 | const tailwindcss = require('tailwindcss') 8 | const autoprefixer = require('autoprefixer') // help tailwindcss to work 9 | 10 | module.exports = { 11 | // Where webpack looks to start building the bundle 12 | entry: [paths.src + '/index.js'], 13 | 14 | // Where webpack outputs the assets and bundles 15 | output: { 16 | path: paths.build, 17 | filename: '[name].bundle.js', 18 | publicPath: '/', 19 | }, 20 | 21 | // Customize the webpack build process 22 | plugins: [ 23 | // Removes/cleans build folders and unused assets when rebuilding 24 | new CleanWebpackPlugin(), 25 | 26 | new MiniCssExtractPlugin({ 27 | filename: 'styles/[name].[contenthash].css', 28 | chunkFilename: '[id].[contenthash].css', 29 | }), 30 | 31 | // Copies files from target to destination folder 32 | new CopyWebpackPlugin({ 33 | patterns: [ 34 | { 35 | from: paths.src + '/assets', 36 | to: 'assets', 37 | globOptions: { 38 | ignore: ['*.DS_Store'], 39 | }, 40 | }, 41 | ], 42 | }), 43 | 44 | // Generates an HTML file from a template 45 | // Generates deprecation warning: https://github.com/jantimon/html-webpack-plugin/issues/1501 46 | new HtmlWebpackPlugin({ 47 | title: 'Project Title', 48 | favicon: paths.src + '/assets/icons/favicon.png', 49 | template: paths.public + '/index.html', // template file 50 | filename: 'index.html', // output file 51 | }), 52 | ], 53 | 54 | // Determine how modules within the project are treated 55 | module: { 56 | rules: [ 57 | // JavaScript: Use Babel to transpile JavaScript files 58 | { test: /\.(js|jsx)$/, exclude: /node_modules/, use: ['babel-loader'] }, 59 | 60 | // Styles: Inject CSS into the head with source maps 61 | { 62 | test: /\.(css|scss|sass)$/, 63 | use: [ 64 | MiniCssExtractPlugin.loader, 65 | 'css-loader', 66 | 'sass-loader', 67 | { 68 | loader: 'postcss-loader', // postcss loader needed for tailwindcss 69 | options: { 70 | postcssOptions: { 71 | ident: 'postcss', 72 | plugins: [tailwindcss, autoprefixer], 73 | }, 74 | }, 75 | }, 76 | ], 77 | }, 78 | 79 | { 80 | test: /\.svg$/, 81 | use: ['@svgr/webpack'], 82 | }, 83 | 84 | // Images: Copy image files to build folder 85 | { test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: 'asset/resource' }, 86 | 87 | // Fonts and SVGs: Inline files 88 | { test: /\.(woff(2)?|eot|ttf|otf|)$/, type: 'asset/inline' }, 89 | ], 90 | }, 91 | } 92 | -------------------------------------------------------------------------------- /config/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const paths = require('./paths') 2 | const Dotenv = require('dotenv-webpack') 3 | const { merge } = require('webpack-merge') 4 | const common = require('./webpack.common.js') 5 | const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin') 6 | 7 | module.exports = merge(common, { 8 | // Set the mode to development or production 9 | mode: 'development', 10 | 11 | // Control how source maps are generated 12 | devtool: 'inline-source-map', 13 | 14 | // Spin up a server for quick development 15 | devServer: { 16 | historyApiFallback: true, 17 | contentBase: paths.build, 18 | open: false, 19 | compress: true, 20 | hot: true, 21 | port: 3000, 22 | }, 23 | 24 | module: { 25 | rules: [ 26 | // ... other rules 27 | { 28 | test: /\.[js]sx?$/, 29 | exclude: /node_modules/, 30 | use: [ 31 | // ... other loaders 32 | { 33 | loader: require.resolve('babel-loader'), 34 | options: { 35 | // ... other options 36 | plugins: [ 37 | // ... other plugins 38 | require.resolve('react-refresh/babel'), 39 | ].filter(Boolean), 40 | }, 41 | }, 42 | ], 43 | }, 44 | ], 45 | }, 46 | plugins: [ 47 | new Dotenv({ 48 | path: './.env.development', 49 | }), 50 | // new webpack.HotModuleReplacementPlugin(), 51 | new ReactRefreshWebpackPlugin(), 52 | ].filter(Boolean), 53 | }) 54 | -------------------------------------------------------------------------------- /config/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const paths = require('./paths') 2 | const Dotenv = require('dotenv-webpack') 3 | const { merge } = require('webpack-merge') 4 | const common = require('./webpack.common.js') 5 | 6 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 7 | const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') 8 | const TerserPlugin = require('terser-webpack-plugin') 9 | 10 | module.exports = merge(common, { 11 | mode: 'production', 12 | devtool: false, 13 | output: { 14 | path: paths.build, 15 | publicPath: '/', 16 | filename: 'js/[name].[contenthash].bundle.js', 17 | }, 18 | plugins: [ 19 | new Dotenv({ 20 | path: './.env.production', 21 | }), 22 | // Extracts CSS into separate files 23 | // Note: style-loader is for development, MiniCssExtractPlugin is for production 24 | new MiniCssExtractPlugin({ 25 | filename: 'styles/[name].[contenthash].css', 26 | chunkFilename: '[id].css', 27 | }), 28 | ], 29 | module: { 30 | rules: [], 31 | }, 32 | optimization: { 33 | minimize: true, 34 | minimizer: [ 35 | // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line 36 | `...`, 37 | new TerserPlugin(), 38 | new CssMinimizerPlugin(), 39 | ], 40 | }, 41 | performance: { 42 | hints: false, 43 | maxEntrypointSize: 512000, 44 | maxAssetSize: 512000, 45 | }, 46 | }) 47 | -------------------------------------------------------------------------------- /config/webpack.stag.js: -------------------------------------------------------------------------------- 1 | const paths = require('./paths') 2 | const Dotenv = require('dotenv-webpack') 3 | const { merge } = require('webpack-merge') 4 | const common = require('./webpack.common.js') 5 | 6 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 7 | const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') 8 | const TerserPlugin = require('terser-webpack-plugin') 9 | 10 | module.exports = merge(common, { 11 | mode: 'production', 12 | devtool: false, 13 | output: { 14 | path: paths.build, 15 | publicPath: '/', 16 | filename: 'js/[name].[contenthash].bundle.js', 17 | }, 18 | plugins: [ 19 | new Dotenv({ 20 | path: './.env.staging', 21 | }), 22 | // Extracts CSS into separate files 23 | // Note: style-loader is for development, MiniCssExtractPlugin is for production 24 | new MiniCssExtractPlugin({ 25 | filename: 'styles/[name].[contenthash].css', 26 | chunkFilename: '[id].css', 27 | }), 28 | ], 29 | module: { 30 | rules: [], 31 | }, 32 | optimization: { 33 | minimize: true, 34 | minimizer: [new OptimizeCssAssetsPlugin(), new TerserPlugin()], 35 | // Once your build outputs multiple chunks, this option will ensure they share the webpack runtime 36 | // instead of having their own. This also helps with long-term caching, since the chunks will only 37 | // change when actual code changes, not the webpack runtime. 38 | runtimeChunk: { 39 | name: 'runtime', 40 | }, 41 | }, 42 | performance: { 43 | hints: false, 44 | maxEntrypointSize: 512000, 45 | maxAssetSize: 512000, 46 | }, 47 | }) 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "name": "Stefan Wüthrich", 4 | "url": "https://altafino.com" 5 | }, 6 | "keywords": [ 7 | "react", 8 | "reactjs", 9 | "webpack", 10 | "boilerplate", 11 | "tailwind" 12 | ], 13 | "license": "MIT", 14 | "name": "react-webpack-5-tailwind-2", 15 | "version": "1.0.1", 16 | "description": "Webpack 6 boilerplate with React 17, Tailwind 2, using babel, sass, with HMR and an optimized production build", 17 | "dependencies": { 18 | "react": "^17.0.2", 19 | "react-dom": "^17.0.2", 20 | "tailwindcss": "^2.2.7" 21 | }, 22 | "main": "index.js", 23 | "scripts": { 24 | "test": "jest", 25 | "start": "webpack serve --config config/webpack.dev.js", 26 | "build": "NODE_ENV=production webpack --config config/webpack.prod.js", 27 | "build-staging": "NODE_ENV=production webpack --config config/webpack.stag.js", 28 | "prettify": "yarn prettier \"**/*.*(js|jsx)\" --ignore-path=.prettierignore --write", 29 | "lint": "eslint src --ext .js,.jsx && yarn prettify", 30 | "lint-fix": "eslint src --ext .js,.jsx --fix && yarn prettify", 31 | "predeploy": "npm run build", 32 | "deploy": "gh-pages -d dist" 33 | }, 34 | "husky": { 35 | "hooks": { 36 | "pre-commit": "yarn lint-staged --verbose" 37 | } 38 | }, 39 | "lint-staged": { 40 | "*.{js,jsx}": [ 41 | "eslint --fix" 42 | ] 43 | }, 44 | "jest": { 45 | "testEnvironment": "jsdom", 46 | "moduleNameMapper": { 47 | "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/__mocks__/fileMock.js", 48 | "\\.(css|less)$": "/__mocks__/styleMock.js" 49 | } 50 | }, 51 | "devDependencies": { 52 | "@babel/core": "^7.18.5", 53 | "@babel/plugin-proposal-class-properties": "^7.17.12", 54 | "@babel/plugin-transform-runtime": "^7.18.5", 55 | "@babel/preset-env": "^7.18.2", 56 | "@babel/preset-react": "^7.17.12", 57 | "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3", 58 | "@svgr/webpack": "^5.5.0", 59 | "@testing-library/jest-dom": "^5.16.4", 60 | "@testing-library/react": "^12.0.0", 61 | "@testing-library/user-event": "^13.2.1", 62 | "autoprefixer": "^10.4.7", 63 | "babel-eslint": "^10.1.0", 64 | "babel-jest": "^27.0.6", 65 | "babel-loader": "^8.2.5", 66 | "clean-webpack-plugin": "*", 67 | "copy-webpack-plugin": "^9.0.1", 68 | "cross-env": "^7.0.3", 69 | "css-loader": "^6.7.1", 70 | "css-minimizer-webpack-plugin": "^3.0.2", 71 | "dotenv-webpack": "^7.1.0", 72 | "eslint": "^7.32.0", 73 | "eslint-config-prettier": "^8.5.0", 74 | "eslint-import-resolver-alias": "^1.1.2", 75 | "eslint-plugin-babel": "^5.3.1", 76 | "eslint-plugin-import": "^2.26.0", 77 | "eslint-plugin-prettier": "^3.4.0", 78 | "eslint-plugin-react": "^7.30.0", 79 | "eslint-plugin-react-hooks": "^4.6.0", 80 | "html-webpack-plugin": "^5.5.0", 81 | "husky": "^7.0.1", 82 | "jest": "^27.0.6", 83 | "lint-staged": "^11.1.2", 84 | "mini-css-extract-plugin": "^2.6.1", 85 | "node-sass": "^6.0.1", 86 | "postcss": "^8.4.14", 87 | "postcss-import": "^14.1.0", 88 | "postcss-loader": "^6.1.1", 89 | "prettier": "^2.7.1", 90 | "react-refresh": "^0.9.0", 91 | "sass-loader": "^12.1.0", 92 | "style-loader": "^3.3.1", 93 | "terser-webpack-plugin": "^5.3.3", 94 | "webpack": "^5.73.0", 95 | "webpack-cli": "^4.10.0", 96 | "webpack-dev-server": "^3.11.2", 97 | "webpack-merge": "^5.8.0" 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-import'), 4 | require('tailwindcss'), 5 | require('autoprefixer'), 6 | ], 7 | } 8 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Boilerplate with Webpack and Tailwind 2 6 | 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react' 2 | 3 | import Logo from './assets/altafino.svg' 4 | import './app.styles.scss' 5 | 6 | class App extends Component { 7 | render() { 8 | return ( 9 |
10 |
11 |
12 | Webpack 6 boilerplate with React 17, Tailwind 2, using babel, sass, 13 | with a hot dev server and an optimized production build. 14 | React Jobs for React JS Developers 15 |
16 | process.env.API_URL:{process.env.API_URL} !!! Make sure to put 17 | both .env.* files in gitignore. 18 |
19 |
20 | 21 | 22 | 23 |
24 |
25 |
26 |
27 | ) 28 | } 29 | } 30 | 31 | export default App 32 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react' 2 | import '@testing-library/jest-dom' 3 | import App from './App' 4 | 5 | test('check first div text', () => { 6 | render() 7 | const linkElement = screen.getByText( 8 | /Webpack 6 boilerplate with React 17, Tailwind 2, using babel/i 9 | ) 10 | expect(linkElement).toBeInTheDocument() 11 | }) 12 | -------------------------------------------------------------------------------- /src/app.styles.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altafino/react-webpack-5-tailwind-2/fee6eb281747501b4435f142d2b9959e18f76305/src/app.styles.scss -------------------------------------------------------------------------------- /src/assets/altafino.svg: -------------------------------------------------------------------------------- 1 | altafino -------------------------------------------------------------------------------- /src/assets/icons/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altafino/react-webpack-5-tailwind-2/fee6eb281747501b4435f142d2b9959e18f76305/src/assets/icons/favicon.png -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom' 2 | import App from './App' 3 | import './index.scss' 4 | 5 | ReactDOM.render(, document.getElementById('root')) 6 | -------------------------------------------------------------------------------- /src/index.scss: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: ['./src/**/*.js'], 3 | darkMode: false, // or 'media' or 'class' 4 | theme: { 5 | extend: {}, 6 | }, 7 | variants: { 8 | extend: {}, 9 | }, 10 | plugins: [], 11 | } 12 | --------------------------------------------------------------------------------