Issue #941
In this tutorial we will be creating a React app with Parcel 2 with Typescript and Tailwind
Install the following dependencies. Parcel supports TypeScript out of the box without any additional configuration.
npm install --save-dev parcel
npm install react react-dom
npm install @types/react @types/react-dom --dev
npm install -D tailwindcss postcss
npx tailwindcss init
We will be adding files to src
folder
src
- index.html
- App.tsx
- App.css
Create a .postcssrc
with the following
{
"plugins": {
"tailwindcss": {}
}
}
Supposed we are adding files in src
folder, allow Tailwind to act in the following content paths in tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{html,js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
In our index.html
, add a placeholder div
to inject later with script
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My Parcel App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="index.tsx"></script>
</body>
</html>
Here is how we inject our React component
import { createRoot } from "react-dom/client"
import App from "./App"
const container = document.getElementById("app")!
const root = createRoot(container)
root.render(<App />);
Our App
component can be simple like this
import React from "react"
import "./App.css"
function App() {
return (
<div className="App">
<header className="App-header">
<a>
Learn React
</a>
</header>
<h1 className="text-5xl font-italic underline text-green-400">Hello world!</h1>
</div>
)
}
export default App
Specify Tailwind layers in App.css
@tailwind base;
@tailwind components;
@tailwind utilities;
We will be adding 2 handy scripts to our package.json
, specifying src/index.html
as our starting point
{
"name": "parcel app",
"version": "1.0.0",
"description": "",
"source": "src/index.html",
"scripts": {
"start": "parcel --open",
"build": "parcel build --no-source-maps"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"parcel": "^2.9.3",
"postcss": "^8.4.27",
"process": "^0.11.10",
"tailwindcss": "^3.3.3",
"typescript": "^5.1.6"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
Read more about source
The source field within any target declared in package.json can specify one or more entry files that are specific to that target. For example, you could build your frontend and backend simultaneously, or your desktop and mobile apps. See below for details about configuring targets.
{
"targets": {
"frontend": {
"source": "app/index.html"
},
"backend": {
"source": "api/index.js"
}
}
}
Now we can just npm run start
to develop and npm run build
to build.
Parcel supports Hot reloading. As you make changes to your code, Parcel automatically rebuilds the changed files and updates your app in the browser
CORS policy
If you access dist/index.html
and get CORS policy error
access to script at 'file:///index.e59da450.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.
It is because we use ES6 module
for script. ES6 modules are subject to same-origin policy, we can’t run it locally without served from a server.
Take a look at Web Extension