Last active
February 17, 2020 00:43
-
-
Save bmingles/72d03b02effa3b77a0fdf794f42db939 to your computer and use it in GitHub Desktop.
NodeJS script to scaffold minimal React + TypeScript app using ParcelJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
/** | |
* Script for scafolding a React + TypeScript app using | |
* ParcelJS as a bundler. | |
* | |
* - TypeScript | |
* - React | |
* - ParcelJS | |
* - Sass | |
* - eslint | |
* - prettier | |
*/ | |
const fs = require('fs') | |
const path = require('path') | |
if (process.argv.length < 3) { | |
console.error('Missing app directory arg.') | |
process.exit(1) | |
} | |
const appRoot = path.resolve(process.argv[2]) | |
const appName = appRoot.substr(appRoot.lastIndexOf(path.sep) + 1) | |
if (fs.existsSync(appRoot)) { | |
console.error(`${appRoot} already exists.`) | |
process.exit(1) | |
} | |
fs.mkdirSync(path.join(appRoot, 'src', 'components'), { recursive: true }) | |
fs.writeFileSync( | |
path.join(appRoot, 'package.json'), | |
`{ | |
"name": "${appName}", | |
"version": "1.0.0", | |
"main": "index.js", | |
"license": "MIT", | |
"devDependencies": { | |
"@types/react": "^16.9.19", | |
"@types/react-dom": "^16.9.5", | |
"@typescript-eslint/eslint-plugin": "^2.19.2", | |
"@typescript-eslint/parser": "^2.19.2", | |
"eslint": "^6.8.0", | |
"eslint-plugin-react": "^7.18.3", | |
"eslint-plugin-react-hooks": "^2.3.0", | |
"node-sass": "^4.13.1", | |
"parcel-bundler": "^1.12.4", | |
"prettier": "^1.19.1", | |
"typescript": "^3.7.5" | |
}, | |
"scripts": { | |
"build": "parcel build index.html", | |
"start": "parcel index.html" | |
}, | |
"dependencies": { | |
"react": "^16.12.0", | |
"react-dom": "^16.12.0" | |
} | |
} | |
` | |
) | |
fs.writeFileSync( | |
path.join(appRoot, 'tsconfig.json'), | |
`{ | |
"compilerOptions": { | |
"downlevelIteration": true, | |
"esModuleInterop": true, | |
"jsx": "react", | |
"lib": [ | |
"dom", | |
"dom.iterable", | |
"esnext" | |
], | |
"module": "commonjs", | |
"moduleResolution": "node", | |
"sourceMap": true, | |
"strict": true | |
}, | |
"exclude": [ | |
"node_modules" | |
], | |
"include": ["src/**/*"] | |
}` | |
) | |
fs.writeFileSync( | |
path.join(appRoot, '.prettierrc.js'), | |
`module.exports = { | |
semi: false, | |
singleQuote: true, | |
trailingComma: 'all', | |
tabWidth: 2, | |
};` | |
) | |
fs.writeFileSync( | |
path.join(appRoot, '.gitignore'), | |
`.cache | |
/dist | |
node_modules` | |
) | |
fs.writeFileSync( | |
path.join(appRoot, 'index.html'), | |
`<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>${appName[0].toUpperCase()}${appName.slice(1)}</title> | |
</head> | |
<body> | |
<div id="app"></div> | |
<script src="src/index.tsx"></script> | |
</body> | |
</html> | |
` | |
) | |
fs.writeFileSync( | |
path.join(appRoot, 'src', 'index.tsx'), | |
`import React from 'react' | |
import ReactDOM from 'react-dom' | |
import { App } from './components' | |
import './index.scss' | |
ReactDOM.render(<App />, document.getElementById('app'))` | |
) | |
fs.writeFileSync( | |
path.join(appRoot, 'src', 'components', 'App.tsx'), | |
`import React from 'react' | |
export interface AppProps {} | |
const App: React.FC<AppProps> = () => <div>App</div> | |
export default App` | |
) | |
fs.writeFileSync( | |
path.join(appRoot, 'src', 'index.scss'), | |
`* { | |
box-sizing: border-box; | |
} | |
body { | |
font-family: sans-serif; | |
font-size: 16px; | |
}` | |
) | |
fs.writeFileSync( | |
path.join(appRoot, 'src', 'components', 'index.ts'), | |
`export { default as App } from './App'` | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment