├── .changeset ├── README.md └── config.json ├── .github └── workflows │ ├── node.js.yml │ └── release.yml ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── LICENSE ├── README.md ├── examples ├── with-javascript │ ├── .gitignore │ ├── craco.config.js │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ └── src │ │ ├── App.css │ │ ├── App.jsx │ │ ├── App.test.jsx │ │ ├── features │ │ └── jest-mocks │ │ │ ├── __mocks__ │ │ │ └── jest-mocks.js │ │ │ ├── jest-mocks.js │ │ │ └── jest-mocks.test.js │ │ ├── index.css │ │ ├── index.jsx │ │ ├── logo.svg │ │ └── setupTests.js ├── with-svgr │ ├── .gitignore │ ├── craco.config.js │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ └── src │ │ ├── App.css │ │ ├── App.jsx │ │ ├── App.test.jsx │ │ ├── index.css │ │ ├── index.jsx │ │ ├── logo.svg │ │ └── setupTests.js └── with-typescript │ ├── .gitignore │ ├── craco.config.js │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.css │ ├── App.test.tsx │ ├── App.tsx │ ├── features │ │ └── jest-mocks │ │ │ ├── __mocks__ │ │ │ └── jest-mocks.ts │ │ │ ├── jest-mocks.test.ts │ │ │ └── jest-mocks.ts │ ├── index.css │ ├── index.tsx │ ├── logo.svg │ ├── react-app-env.d.ts │ └── setupTests.ts │ └── tsconfig.json ├── package.json ├── packages └── craco-esbuild │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ └── src │ └── index.js ├── pnpm-lock.yaml └── pnpm-workspace.yaml /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.6.3/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { "repo": "pradel/create-react-app-esbuild" } 6 | ], 7 | "commit": false, 8 | "linked": [], 9 | "access": "public", 10 | "baseBranch": "main", 11 | "updateInternalDependencies": "patch", 12 | "ignore": [] 13 | } 14 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | # Test default react-scripts to compare time 11 | test-react-scripts: 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | node-version: [18.x, 20.x] 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - uses: pnpm/action-setup@v2 22 | with: 23 | version: 8.15.1 24 | 25 | - name: Use Node.js ${{ matrix.node-version }} 26 | uses: actions/setup-node@v2 27 | with: 28 | node-version: ${{ matrix.node-version }} 29 | cache: 'pnpm' 30 | 31 | - name: Install dependencies 32 | run: pnpm install 33 | 34 | - name: Compile create-react-app examples using react-scripts 35 | run: | 36 | pnpm run --filter "with-*" build-react-scripts 37 | 38 | - name: Test create-react-app examples using react-scripts 39 | run: | 40 | pnpm run --filter "with-*" test-react-scripts 41 | 42 | test: 43 | runs-on: ubuntu-latest 44 | 45 | strategy: 46 | matrix: 47 | node-version: [18.x, 20.x] 48 | 49 | steps: 50 | - uses: actions/checkout@v2 51 | 52 | - uses: pnpm/action-setup@v2 53 | with: 54 | version: 8.15.1 55 | 56 | - name: Use Node.js ${{ matrix.node-version }} 57 | uses: actions/setup-node@v2 58 | with: 59 | node-version: ${{ matrix.node-version }} 60 | cache: 'pnpm' 61 | 62 | - name: Install dependencies 63 | run: pnpm install 64 | 65 | - name: Compile create-react-app examples using craco 66 | run: | 67 | pnpm run --filter "with-*" build 68 | 69 | - name: Test create-react-app examples using craco 70 | run: | 71 | pnpm run --filter "with-*" test 72 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | 7 | jobs: 8 | release: 9 | name: Release 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout Repo 13 | uses: actions/checkout@v2 14 | with: 15 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 16 | fetch-depth: 0 17 | 18 | - uses: pnpm/action-setup@v2 19 | with: 20 | version: 8.15.1 21 | 22 | - name: Use Node.js 20.x 23 | uses: actions/setup-node@v2 24 | with: 25 | node-version: 20.x 26 | cache: 'pnpm' 27 | 28 | - name: Install dependencies 29 | run: pnpm install 30 | 31 | - name: Create Release Pull Request or Publish to npm 32 | id: changesets 33 | uses: changesets/action@v1 34 | with: 35 | version: pnpm run version 36 | publish: pnpm run release 37 | commit: 'chore: update versions' 38 | title: 'chore: version packages' 39 | env: 40 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 41 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | pnpm lint-staged 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Léo Pradel 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 | # 🚀 create-react-app-esbuild 🚀 2 | 3 | Use [esbuild](https://github.com/evanw/esbuild) in your [create-react-app](https://create-react-app.dev/) for faster compilation, development and tests. 4 | 5 | ## Features 6 | 7 | - Replace babel-loader with esbuild during development 8 | - Replace babel-loader with esbuild for faster build time 9 | - Replace terser with esbuild for faster build time 10 | - Replace OptimizeCssAssetsWebpackPlugin with esbuild for faster build time 11 | - Use esbuild when running jest 12 | 13 | ## Getting started 14 | 15 | Follow the [guide](https://github.com/pradel/create-react-app-esbuild/blob/main/packages/craco-esbuild/README.md) to setup your project. 16 | 17 | ## FAQ 18 | 19 | ### Why is it faster? 20 | 21 | Internally create-react-app use babel to compile the javascript / typescript files of your application. By using craco-esbuild, you use the [esbuild](https://github.com/evanw/esbuild) compiler to compile your app instead of babel. esbuild is a super fast javascript / typescript bundler and minifier written in Go. 22 | 23 | ### What is craco and why do I need it? 24 | 25 | [craco](https://github.com/gsoft-inc/craco) (**C**reate **R**eact **A**pp **C**onfiguration **O**verride) is an easy and comprehensible configuration layer for create-react-app. By using craco you can customise the create-react-app configuration without ejecting. 26 | 27 | ## License 28 | 29 | MIT © [Léo Pradel](https://www.leopradel.com/) 30 | -------------------------------------------------------------------------------- /examples/with-javascript/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /examples/with-javascript/craco.config.js: -------------------------------------------------------------------------------- 1 | const CracoEsbuildPlugin = require('craco-esbuild'); 2 | 3 | module.exports = { 4 | plugins: [ 5 | { 6 | plugin: CracoEsbuildPlugin, 7 | }, 8 | ], 9 | }; 10 | -------------------------------------------------------------------------------- /examples/with-javascript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-javascript", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@babel/plugin-transform-modules-commonjs": "^7.23.3", 7 | "@craco/craco": "7.0.0", 8 | "@testing-library/jest-dom": "^6.3.0", 9 | "@testing-library/react": "^12.1.2", 10 | "@testing-library/user-event": "^13.5.0", 11 | "craco-esbuild": "workspace:craco-esbuild", 12 | "react": "^17.0.2", 13 | "react-dom": "^17.0.2", 14 | "react-scripts": "5.0.0" 15 | }, 16 | "scripts": { 17 | "start": "craco start", 18 | "start-react-scripts": "react-scripts start", 19 | "build": "craco build", 20 | "build-react-scripts": "react-scripts build", 21 | "test": "craco test", 22 | "test-react-scripts": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/with-javascript/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pradel/create-react-app-esbuild/6a8be4d0b6d9c9b6b569f37b48862ba98f5bb176/examples/with-javascript/public/favicon.ico -------------------------------------------------------------------------------- /examples/with-javascript/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/with-javascript/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pradel/create-react-app-esbuild/6a8be4d0b6d9c9b6b569f37b48862ba98f5bb176/examples/with-javascript/public/logo192.png -------------------------------------------------------------------------------- /examples/with-javascript/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pradel/create-react-app-esbuild/6a8be4d0b6d9c9b6b569f37b48862ba98f5bb176/examples/with-javascript/public/logo512.png -------------------------------------------------------------------------------- /examples/with-javascript/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/with-javascript/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/with-javascript/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/with-javascript/src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/App.js and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /examples/with-javascript/src/App.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/with-javascript/src/features/jest-mocks/__mocks__/jest-mocks.js: -------------------------------------------------------------------------------- 1 | export const jestMockWorking = true; 2 | -------------------------------------------------------------------------------- /examples/with-javascript/src/features/jest-mocks/jest-mocks.js: -------------------------------------------------------------------------------- 1 | export const jestMockWorking = false; 2 | -------------------------------------------------------------------------------- /examples/with-javascript/src/features/jest-mocks/jest-mocks.test.js: -------------------------------------------------------------------------------- 1 | import { jestMockWorking } from './jest-mocks'; 2 | 3 | jest.mock('./jest-mocks'); 4 | 5 | test('Value should be true if mocks is working', () => { 6 | expect(jestMockWorking).toBe(true); 7 | }); 8 | -------------------------------------------------------------------------------- /examples/with-javascript/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/with-javascript/src/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ); 12 | -------------------------------------------------------------------------------- /examples/with-javascript/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/with-javascript/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /examples/with-svgr/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /examples/with-svgr/craco.config.js: -------------------------------------------------------------------------------- 1 | const CracoEsbuildPlugin = require('craco-esbuild'); 2 | 3 | module.exports = { 4 | plugins: [ 5 | { 6 | plugin: CracoEsbuildPlugin, 7 | options: { 8 | enableSvgr: true, 9 | }, 10 | }, 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /examples/with-svgr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-svgr", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@craco/craco": "7.0.0", 7 | "@testing-library/jest-dom": "^6.3.0", 8 | "@testing-library/react": "^12.1.2", 9 | "@testing-library/user-event": "^13.5.0", 10 | "craco-esbuild": "workspace:craco-esbuild", 11 | "react": "^17.0.2", 12 | "react-dom": "^17.0.2", 13 | "react-scripts": "5.0.0" 14 | }, 15 | "scripts": { 16 | "start": "craco start", 17 | "start-react-scripts": "react-scripts start", 18 | "build": "craco build", 19 | "build-react-scripts": "react-scripts build", 20 | "test": "craco test", 21 | "test-react-scripts": "react-scripts test", 22 | "eject": "react-scripts eject" 23 | }, 24 | "eslintConfig": { 25 | "extends": [ 26 | "react-app", 27 | "react-app/jest" 28 | ] 29 | }, 30 | "browserslist": { 31 | "production": [ 32 | ">0.2%", 33 | "not dead", 34 | "not op_mini all" 35 | ], 36 | "development": [ 37 | "last 1 chrome version", 38 | "last 1 firefox version", 39 | "last 1 safari version" 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/with-svgr/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pradel/create-react-app-esbuild/6a8be4d0b6d9c9b6b569f37b48862ba98f5bb176/examples/with-svgr/public/favicon.ico -------------------------------------------------------------------------------- /examples/with-svgr/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/with-svgr/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pradel/create-react-app-esbuild/6a8be4d0b6d9c9b6b569f37b48862ba98f5bb176/examples/with-svgr/public/logo192.png -------------------------------------------------------------------------------- /examples/with-svgr/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pradel/create-react-app-esbuild/6a8be4d0b6d9c9b6b569f37b48862ba98f5bb176/examples/with-svgr/public/logo512.png -------------------------------------------------------------------------------- /examples/with-svgr/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/with-svgr/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/with-svgr/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/with-svgr/src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ReactComponent as Logo } from './logo.svg'; 3 | import './App.css'; 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | 10 |

11 | Edit src/App.js and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /examples/with-svgr/src/App.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/with-svgr/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/with-svgr/src/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ); 12 | -------------------------------------------------------------------------------- /examples/with-svgr/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/with-svgr/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /examples/with-typescript/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /examples/with-typescript/craco.config.js: -------------------------------------------------------------------------------- 1 | const CracoEsbuildPlugin = require('craco-esbuild'); 2 | 3 | module.exports = { 4 | plugins: [ 5 | { 6 | plugin: CracoEsbuildPlugin, 7 | }, 8 | ], 9 | }; 10 | -------------------------------------------------------------------------------- /examples/with-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-typescript", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@babel/plugin-transform-modules-commonjs": "^7.23.3", 7 | "@craco/craco": "7.0.0", 8 | "@testing-library/jest-dom": "^6.3.0", 9 | "@testing-library/react": "^12.1.2", 10 | "@testing-library/user-event": "^13.5.0", 11 | "@types/jest": "^28.0.0", 12 | "@types/node": "^18.19.18", 13 | "@types/react": "^17.0.38", 14 | "@types/react-dom": "^17.0.11", 15 | "craco-esbuild": "workspace:craco-esbuild", 16 | "react": "^17.0.2", 17 | "react-dom": "^17.0.2", 18 | "react-scripts": "5.0.0", 19 | "typescript": "^4.5.4" 20 | }, 21 | "scripts": { 22 | "start": "craco start", 23 | "start-react-scripts": "react-scripts start", 24 | "build": "craco build", 25 | "build-react-scripts": "react-scripts build", 26 | "test": "craco test", 27 | "test-react-scripts": "react-scripts test", 28 | "eject": "react-scripts eject" 29 | }, 30 | "eslintConfig": { 31 | "extends": [ 32 | "react-app", 33 | "react-app/jest" 34 | ] 35 | }, 36 | "browserslist": { 37 | "production": [ 38 | ">0.2%", 39 | "not dead", 40 | "not op_mini all" 41 | ], 42 | "development": [ 43 | "last 1 chrome version", 44 | "last 1 firefox version", 45 | "last 1 safari version" 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/with-typescript/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pradel/create-react-app-esbuild/6a8be4d0b6d9c9b6b569f37b48862ba98f5bb176/examples/with-typescript/public/favicon.ico -------------------------------------------------------------------------------- /examples/with-typescript/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/with-typescript/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pradel/create-react-app-esbuild/6a8be4d0b6d9c9b6b569f37b48862ba98f5bb176/examples/with-typescript/public/logo192.png -------------------------------------------------------------------------------- /examples/with-typescript/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pradel/create-react-app-esbuild/6a8be4d0b6d9c9b6b569f37b48862ba98f5bb176/examples/with-typescript/public/logo512.png -------------------------------------------------------------------------------- /examples/with-typescript/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/with-typescript/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/with-typescript/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/with-typescript/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/with-typescript/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/App.tsx and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /examples/with-typescript/src/features/jest-mocks/__mocks__/jest-mocks.ts: -------------------------------------------------------------------------------- 1 | export const jestMockWorking = true; 2 | -------------------------------------------------------------------------------- /examples/with-typescript/src/features/jest-mocks/jest-mocks.test.ts: -------------------------------------------------------------------------------- 1 | import { jestMockWorking } from './jest-mocks'; 2 | 3 | jest.mock('./jest-mocks'); 4 | 5 | test('Value should be true if mocks is working', () => { 6 | expect(jestMockWorking).toBe(true); 7 | }); 8 | -------------------------------------------------------------------------------- /examples/with-typescript/src/features/jest-mocks/jest-mocks.ts: -------------------------------------------------------------------------------- 1 | export const jestMockWorking = false; 2 | -------------------------------------------------------------------------------- /examples/with-typescript/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/with-typescript/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ); 12 | -------------------------------------------------------------------------------- /examples/with-typescript/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/with-typescript/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/with-typescript/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /examples/with-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx", 18 | "types": ["jest", "@testing-library/jest-dom"] 19 | }, 20 | "include": ["src"] 21 | } 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "prettier": "prettier --write \"**/*.{js,ts,tsx,css,scss,json,md,mdx,yml}\"", 5 | "version": "pnpm changeset version && pnpm install --lockfile-only", 6 | "release": "pnpm changeset publish", 7 | "prepare": "husky install" 8 | }, 9 | "prettier": { 10 | "singleQuote": true 11 | }, 12 | "engines": { 13 | "node": ">=18.0.0" 14 | }, 15 | "lint-staged": { 16 | "*.{js,ts,tsx,css,scss,json,md,mdx,yml}": [ 17 | "prettier --write", 18 | "git add" 19 | ] 20 | }, 21 | "devDependencies": { 22 | "@changesets/changelog-github": "0.4.2", 23 | "@changesets/cli": "2.19.0", 24 | "husky": "7.0.4", 25 | "lint-staged": "12.1.7", 26 | "prettier": "2.5.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/craco-esbuild/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.6.1 4 | 5 | ### Patch Changes 6 | 7 | - [#77](https://github.com/pradel/create-react-app-esbuild/pull/77) [`14c3d80`](https://github.com/pradel/create-react-app-esbuild/commit/14c3d80ee8799615d23dd47075c1752fcc1742c4) Thanks [@pradel](https://github.com/pradel)! - Fix invalid craco version in package.json. 8 | 9 | ## 0.6.0 10 | 11 | ### Minor Changes 12 | 13 | - [#73](https://github.com/pradel/create-react-app-esbuild/pull/73) [`935c2f9`](https://github.com/pradel/create-react-app-esbuild/commit/935c2f9ed35c9ef37ad3750652ad163508c50cb8) Thanks [@Crecket](https://github.com/Crecket)! - Updated esbuild-loader to v4 and craco to v7. 14 | 15 | ## 0.5.2 16 | 17 | ### Patch Changes 18 | 19 | - [#63](https://github.com/pradel/create-react-app-esbuild/pull/63) [`8aa74cd`](https://github.com/pradel/create-react-app-esbuild/commit/8aa74cdce93d19955ac2050fbf6512981a9eaa0b) Thanks [@jiejasonliu](https://github.com/jiejasonliu)! - Include @craco/craco@7.0.0-alpha.* versions in peerDependencies 20 | 21 | ## 0.5.1 22 | 23 | ### Patch Changes 24 | 25 | - [#57](https://github.com/pradel/create-react-app-esbuild/pull/57) [`615f523`](https://github.com/pradel/create-react-app-esbuild/commit/615f52337d8661b7307768f0cb5665b7e678559c) Thanks [@ottob](https://github.com/ottob)! - Add craco 7 to peerDependencies 26 | 27 | ## 0.5.0 28 | 29 | ### Minor Changes 30 | 31 | - [#48](https://github.com/pradel/create-react-app-esbuild/pull/48) [`f276f85`](https://github.com/pradel/create-react-app-esbuild/commit/f276f850732c1faf8e5cb6fd0471f66c691f9ba2) Thanks [@pradel](https://github.com/pradel)! - 🚀 create-react-app 5 is now supported 🚀 32 | 33 | ## Breaking Changes 34 | 35 | - Removed the `enableSvgr` and `svgrOptions` options. Svgr is now working out of the box. 36 | - Drop support for CRA 3 and 4. As many underlying libraries have changed, CRA 4 and 3 are no longer supported. Check the [CRA changelog](https://github.com/facebook/create-react-app/releases/tag/v5.0.0) to see what changed. 37 | 38 | ## Migrating from 0.4.X to 0.5.X 39 | 40 | - You will first need to migrate your project to CRA 5. See the CRA [Migration guide](https://github.com/facebook/create-react-app/releases/tag/v5.0.0) for more information. 41 | - Upgrade `craco-esbuild` to version 0.5.0 or higher in your project. 42 | - If you are using `enableSvgr` or `svgrOptions` you can remove them from the `craco.config.js` file. Svgr is now working out of the box. 43 | 44 | ## 0.4.5 45 | 46 | ### Patch Changes 47 | 48 | - [#49](https://github.com/pradel/create-react-app-esbuild/pull/49) [`9e09177`](https://github.com/pradel/create-react-app-esbuild/commit/9e09177ca75051749705b9b957c07b01aabfd0b9) Thanks [@pradel](https://github.com/pradel)! - Use require.resolve to import the '@svgr/webpack' loader, this solve an issue that monorepo can have. 49 | 50 | ## 0.4.4 51 | 52 | ### Patch Changes 53 | 54 | - [#46](https://github.com/pradel/create-react-app-esbuild/pull/46) [`109a742`](https://github.com/pradel/create-react-app-esbuild/commit/109a7429b780c2c6dd1f55d12ae11e3ca72ed36a) Thanks [@pradel](https://github.com/pradel)! - Automate release process. 55 | 56 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 57 | 58 | ### [0.4.3](https://github.com/pradel/create-react-app-esbuild/compare/v0.4.2...v0.4.3) (2021-12-14) 59 | 60 | ### Features 61 | 62 | - add `svgrOptions` to customize svgr plugin behavior ([#44](https://github.com/pradel/create-react-app-esbuild/issues/44)) ([4ebde9f](https://github.com/pradel/create-react-app-esbuild/commit/4ebde9fd73a0f243531a4570feb7873f8cacc55e)) 63 | 64 | ### [0.4.2](https://github.com/pradel/create-react-app-esbuild/compare/v0.4.1...v0.4.2) (2021-10-12) 65 | 66 | ### Features 67 | 68 | - replace minifier only when used ([#42](https://github.com/pradel/create-react-app-esbuild/issues/42)) ([7453334](https://github.com/pradel/create-react-app-esbuild/commit/745333410391d4bb97fef76d21c0afbc2e65b631)) 69 | 70 | ### [0.4.1](https://github.com/pradel/create-react-app-esbuild/compare/v0.4.0...v0.4.1) (2021-09-22) 71 | 72 | ### Bug Fixes 73 | 74 | - compatability with node 12 ([#40](https://github.com/pradel/create-react-app-esbuild/issues/40)) ([269dd30](https://github.com/pradel/create-react-app-esbuild/commit/269dd3055e59930ca4534aa7ab124f02883823e6)) 75 | 76 | ## [0.4.0](https://github.com/pradel/create-react-app-esbuild/compare/v0.3.4...v0.4.0) (2021-09-06) 77 | 78 | ### ⚠ BREAKING CHANGES 79 | 80 | - add esbuild css minification (#36) 81 | 82 | ### Features 83 | 84 | - add esbuild css minification ([#36](https://github.com/pradel/create-react-app-esbuild/issues/36)) ([35214fb](https://github.com/pradel/create-react-app-esbuild/commit/35214fb9325f52f7a4406afc7c9359650aa820da)) 85 | 86 | ### Miscellaneous Chores 87 | 88 | - upgrade deps ([#37](https://github.com/pradel/create-react-app-esbuild/issues/37)) ([2d7079e](https://github.com/pradel/create-react-app-esbuild/commit/2d7079e81269bed793b447d6c854e53dd314afc2)) 89 | 90 | ### [0.3.4](https://github.com/pradel/create-react-app-esbuild/compare/v0.3.3...v0.3.4) (2021-08-16) 91 | 92 | ### Features 93 | 94 | - add `esbuildJestOptions` to override esbuild-jest's options ([#34](https://github.com/pradel/create-react-app-esbuild/issues/34)) ([cbd7d03](https://github.com/pradel/create-react-app-esbuild/commit/cbd7d031011f5ce10f8217c06868998ddf9f5af0)) 95 | 96 | ### Miscellaneous Chores 97 | 98 | - prettier ([6b8e8e4](https://github.com/pradel/create-react-app-esbuild/commit/6b8e8e469ed71b9812d8553260b952cee11e2edd)) 99 | 100 | ### [0.3.3](https://github.com/pradel/create-react-app-esbuild/compare/v0.3.2...v0.3.3) (2021-07-25) 101 | 102 | ### Documentation 103 | 104 | - improve example for typescript users ([2517cbc](https://github.com/pradel/create-react-app-esbuild/commit/2517cbcaf965a339002c2fefa7368b12a90ea58c)) 105 | 106 | ### [0.3.2](https://github.com/pradel/create-react-app-esbuild/compare/v0.3.1...v0.3.2) (2021-04-28) 107 | 108 | ### Miscellaneous Chores 109 | 110 | - upgrade deps ([#25](https://github.com/pradel/create-react-app-esbuild/issues/25)) ([f27f4e9](https://github.com/pradel/create-react-app-esbuild/commit/f27f4e9c4ad5dcb5a0e51106e0d667c338bda372)) 111 | 112 | ### [0.3.1](https://github.com/pradel/create-react-app-esbuild/compare/v0.3.0...v0.3.1) (2021-03-16) 113 | 114 | ### Bug Fixes 115 | 116 | - remove ESBuildPlugin import. ([#21](https://github.com/pradel/create-react-app-esbuild/issues/21)) ([2e25db5](https://github.com/pradel/create-react-app-esbuild/commit/2e25db51fd8678fcd8475a7abb5d75140ec0d0bb)) 117 | 118 | ## [0.3.0](https://github.com/pradel/create-react-app-esbuild/compare/v0.2.1...v0.3.0) (2021-03-04) 119 | 120 | ### Features 121 | 122 | - add svgr support ([#14](https://github.com/pradel/create-react-app-esbuild/issues/14)) ([1cac975](https://github.com/pradel/create-react-app-esbuild/commit/1cac975b3e487912e595ad803cf773e5b58de974)) 123 | 124 | ### [0.2.1](https://github.com/pradel/create-react-app-esbuild/compare/v0.2.0...v0.2.1) (2021-02-27) 125 | 126 | ### Bug Fixes 127 | 128 | - upgrade esbuild-jest to support jest mocks ([#16](https://github.com/pradel/create-react-app-esbuild/issues/16)) ([68dae43](https://github.com/pradel/create-react-app-esbuild/commit/68dae4360a01e692461d08b673ce61c8c196b777)) 129 | 130 | ### Miscellaneous Chores 131 | 132 | - upgrade esbuild-jest to 0.4 ([#13](https://github.com/pradel/create-react-app-esbuild/issues/13)) ([7db4e35](https://github.com/pradel/create-react-app-esbuild/commit/7db4e35a36f991f9e405d664b510875e2ed08a0c)) 133 | 134 | ### Documentation 135 | 136 | - document `includePaths` option ([49a9b1d](https://github.com/pradel/create-react-app-esbuild/commit/49a9b1dc6f10422cc5c413196c496431629cef3b)) 137 | 138 | ## 0.2.0 (2021-01-18) 139 | 140 | ### Features 141 | 142 | - custom include paths and esbuild jest config ([#5](https://github.com/pradel/create-react-app-esbuild/issues/5)) ([3438f09](https://github.com/pradel/create-react-app-esbuild/commit/3438f092f66e454119b03324e6387dbbe5a0261f)) 143 | - first version ([#1](https://github.com/pradel/create-react-app-esbuild/issues/1)) ([318ace0](https://github.com/pradel/create-react-app-esbuild/commit/318ace0957961e2482d45e041fc969a6bbaf4282)) 144 | 145 | ### Miscellaneous Chores 146 | 147 | - automate release ([#10](https://github.com/pradel/create-react-app-esbuild/issues/10)) ([4b9048c](https://github.com/pradel/create-react-app-esbuild/commit/4b9048cb353d2897b21d4b0fea3bcbfdca7a56f1)) 148 | - fix plugin name ([87442e0](https://github.com/pradel/create-react-app-esbuild/commit/87442e01067819b857766dfe9abd787a9ea8c61a)) 149 | - improve documentation ([efd3ffe](https://github.com/pradel/create-react-app-esbuild/commit/efd3ffed875aced377970ff36fb0271ce41c69a6)) 150 | - update esbuild-loader to 2.8.0 ([#9](https://github.com/pradel/create-react-app-esbuild/issues/9)) ([f5470af](https://github.com/pradel/create-react-app-esbuild/commit/f5470af7298f5a8b078447a20c5991e554b4bdac)) 151 | - upgrade deps ([#3](https://github.com/pradel/create-react-app-esbuild/issues/3)) ([682f8c3](https://github.com/pradel/create-react-app-esbuild/commit/682f8c352fe670964e88e05897e9b37bd0c82cbd)) 152 | -------------------------------------------------------------------------------- /packages/craco-esbuild/README.md: -------------------------------------------------------------------------------- 1 | # 🚀 craco-esbuild 🚀 2 | 3 | Use [esbuild](https://github.com/evanw/esbuild) in your [create-react-app](https://create-react-app.dev/) with [craco](https://github.com/gsoft-inc/craco) for faster compilation, development and tests. 4 | 5 | ## Features 6 | 7 | - Replace babel-loader with esbuild during development 8 | - Replace babel-loader with esbuild for faster build time 9 | - Replace terser with esbuild for faster build time 10 | - Replace OptimizeCssAssetsWebpackPlugin with esbuild for faster build time 11 | - Use esbuild when running jest 12 | 13 | ## Installation 14 | 15 | Run the following command to install `craco-esbuild` in your project: 16 | 17 | ```sh 18 | yarn add --dev craco-esbuild @craco/craco 19 | ``` 20 | OR 21 | ```sh 22 | npm install --save-dev craco-esbuild @craco/craco 23 | ``` 24 | 25 | ## Usage 26 | 27 | Add this configuration to your `craco.config.js` configuration file: 28 | 29 | ```js 30 | // craco.config.js 31 | const CracoEsbuildPlugin = require('craco-esbuild'); 32 | 33 | module.exports = { 34 | plugins: [{ plugin: CracoEsbuildPlugin }], 35 | }; 36 | ``` 37 | 38 | To use `craco` instead of `react-scripts` to manage our application, edit the `scripts` section of your `package.json`. 39 | 40 | ```diff 41 | /* package.json */ 42 | 43 | "scripts": { 44 | - "start": "react-scripts start", 45 | + "start": "craco start", 46 | - "build": "react-scripts build", 47 | + "build": "craco build" 48 | - "test": "react-scripts test", 49 | + "test": "craco test" 50 | } 51 | ``` 52 | 53 | ## Configuration 54 | 55 | You can configure the options of the plugin by passing an `options` object. 56 | 57 | - `esbuildLoaderOptions`: customise the options passed down to the `esbuild` loader. _Note: This will be used only by webpack_ 58 | - `esbuildMinimizerOptions`: customise the options passed down to `ESBuildMinifyPlugin`. _Note: This will be used only by webpack_ 59 | - `includePaths`: include external directories in loader. 60 | - `skipEsbuildJest`: Avoid using `esbuild-jest` for jest configuration. Could be useful to avoid compatibility issues with transpiling tests. 61 | - `esbuildJestOptions`: customise the [options](https://github.com/aelbore/esbuild-jest#setting-up-jest-config-file-with-transformoptions) passed down to the `esbuild-jest` transformer. 62 | 63 | For example add this configuration to your `craco.config.js` configuration file: 64 | 65 | ```js 66 | // craco.config.js 67 | const CracoEsbuildPlugin = require('craco-esbuild'); 68 | 69 | module.exports = { 70 | plugins: [ 71 | { 72 | plugin: CracoEsbuildPlugin, 73 | options: { 74 | includePaths: ['/external/dir/with/components'], // Optional. If you want to include components which are not in src folder 75 | esbuildLoaderOptions: { 76 | // Optional. Defaults to auto-detect loader. 77 | loader: 'jsx', // Set the value to 'tsx' if you use typescript 78 | target: 'es2015', 79 | }, 80 | esbuildMinimizerOptions: { 81 | // Optional. Defaults to: 82 | target: 'es2015', 83 | css: true, // if true, OptimizeCssAssetsWebpackPlugin will also be replaced by esbuild. 84 | }, 85 | skipEsbuildJest: false, // Optional. Set to true if you want to use babel for jest tests, 86 | esbuildJestOptions: { 87 | loaders: { 88 | '.ts': 'ts', 89 | '.tsx': 'tsx', 90 | }, 91 | }, 92 | }, 93 | }, 94 | ], 95 | }; 96 | ``` 97 | 98 | ## License 99 | 100 | MIT © [Léo Pradel](https://www.leopradel.com/) 101 | -------------------------------------------------------------------------------- /packages/craco-esbuild/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "craco-esbuild", 3 | "version": "0.6.1", 4 | "main": "src/index.js", 5 | "repository": "https://github.com/pradel/create-react-app-esbuild.git", 6 | "author": "Leo Pradel ", 7 | "license": "MIT", 8 | "files": [ 9 | "src" 10 | ], 11 | "peerDependencies": { 12 | "@craco/craco": "^7.0.0", 13 | "react-scripts": "^5.0.0" 14 | }, 15 | "dependencies": { 16 | "esbuild-jest": "0.5.0", 17 | "esbuild-loader": "^4.0.1" 18 | }, 19 | "devDependencies": { 20 | "@craco/craco": "7.0.0", 21 | "react-scripts": "5.0.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/craco-esbuild/src/index.js: -------------------------------------------------------------------------------- 1 | const { loaderByName, removeLoaders, addAfterLoader } = require('@craco/craco'); 2 | const { EsbuildPlugin } = require('esbuild-loader'); 3 | 4 | const removeMinimizer = (webpackConfig, name) => { 5 | const idx = webpackConfig.optimization.minimizer.findIndex( 6 | (m) => m.constructor.name === name 7 | ); 8 | webpackConfig.optimization.minimizer.splice(idx, 1); 9 | }; 10 | 11 | const replaceMinimizer = (webpackConfig, name, minimizer) => { 12 | const idx = webpackConfig.optimization.minimizer.findIndex( 13 | (m) => m.constructor.name === name 14 | ); 15 | idx > -1 && webpackConfig.optimization.minimizer.splice(idx, 1, minimizer); 16 | }; 17 | 18 | module.exports = { 19 | /** 20 | * To process the js/ts files we replace the babel-loader with the esbuild-loader 21 | */ 22 | overrideWebpackConfig: ({ 23 | webpackConfig, 24 | pluginOptions, 25 | context: { paths }, 26 | }) => { 27 | const esbuildLoaderOptions = 28 | pluginOptions && pluginOptions.esbuildLoaderOptions; 29 | 30 | // add includePaths custom option, for including files/components in other folders than src 31 | // Used as in addition to paths.appSrc, optional parameter. 32 | const optionalIncludes = 33 | (pluginOptions && pluginOptions.includePaths) || []; 34 | 35 | // add esbuild-loader 36 | addAfterLoader(webpackConfig, loaderByName('babel-loader'), { 37 | test: /\.(js|mjs|jsx|ts|tsx)$/, 38 | include: [paths.appSrc, ...optionalIncludes], 39 | loader: require.resolve('esbuild-loader'), 40 | options: esbuildLoaderOptions 41 | ? esbuildLoaderOptions 42 | : { 43 | target: 'es2015', 44 | }, 45 | }); 46 | 47 | // remove the babel loaders 48 | removeLoaders(webpackConfig, loaderByName('babel-loader')); 49 | 50 | // Replace terser with esbuild 51 | const minimizerOptions = (pluginOptions || {}).esbuildMinimizerOptions || { 52 | target: 'es2015', 53 | css: true, 54 | }; 55 | replaceMinimizer( 56 | webpackConfig, 57 | 'TerserPlugin', 58 | new EsbuildPlugin(minimizerOptions) 59 | ); 60 | // remove the css OptimizeCssAssetsWebpackPlugin 61 | if (minimizerOptions.css) { 62 | removeMinimizer(webpackConfig, 'OptimizeCssAssetsWebpackPlugin'); 63 | } 64 | return webpackConfig; 65 | }, 66 | 67 | /** 68 | * To process the js/ts files we replace the babel-loader with the esbuild jest loader 69 | */ 70 | overrideJestConfig: ({ jestConfig, pluginOptions }) => { 71 | if (pluginOptions && pluginOptions.skipEsbuildJest) return jestConfig; 72 | 73 | const defaultEsbuildJestOptions = { 74 | loaders: { 75 | '.js': 'jsx', 76 | '.test.js': 'jsx', 77 | '.ts': 'tsx', 78 | '.test.ts': 'tsx', 79 | }, 80 | }; 81 | 82 | const esbuildJestOptions = 83 | (pluginOptions && pluginOptions.esbuildJestOptions) || 84 | defaultEsbuildJestOptions; 85 | 86 | // Replace babel transform with esbuild 87 | // babelTransform is first transformer key 88 | /* 89 | transform: 90 | { 91 | '^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': 'node_modules\\react-scripts\\config\\jest\\babelTransform.js', 92 | '^.+\\.css$': 'node_modules\\react-scripts\\config\\jest\\cssTransform.js', 93 | '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'node_modules\\react-scripts\\config\\jest\\fileTransform.js' 94 | } 95 | */ 96 | const babelKey = Object.keys(jestConfig.transform)[0]; 97 | 98 | // We replace babelTransform and add loaders to esbuild-jest 99 | jestConfig.transform[babelKey] = [ 100 | require.resolve('esbuild-jest'), 101 | esbuildJestOptions, 102 | ]; 103 | 104 | // Adds loader to all other transform options (2 in this case: cssTransform and fileTransform) 105 | // Reason for this is esbuild-jest plugin. It considers only loaders or other options from the last transformer 106 | // You can see it for yourself in: /node_modules/esbuild-jest/esbuid-jest.js:21 getOptions method 107 | // also in process method line 32 gives empty loaders, because options is already empty object 108 | // Issue reported here: https://github.com/aelbore/esbuild-jest/issues/18 109 | Object.keys(jestConfig.transform).forEach((key) => { 110 | if (babelKey === key) return; // ebuild-jest transform, already has loader 111 | 112 | // Checks if value is array, usually it's not 113 | // Our example is above on 70-72 lines. Usually default is: {"\\.[jt]sx?$": "babel-jest"} 114 | // (https://jestjs.io/docs/en/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object) 115 | // But we have to cover all the cases 116 | if ( 117 | Array.isArray(jestConfig.transform[key]) && 118 | jestConfig.transform[key].length === 1 119 | ) { 120 | jestConfig.transform[key].push(esbuildJestOptions); 121 | } else { 122 | jestConfig.transform[key] = [ 123 | jestConfig.transform[key], 124 | esbuildJestOptions, 125 | ]; 126 | } 127 | }); 128 | 129 | return jestConfig; 130 | }, 131 | }; 132 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "packages/**" 3 | - "examples/**" 4 | --------------------------------------------------------------------------------