DEV Community

Cover image for Começando um projeto Web com TypeScript
Guilherme Siquinelli
Guilherme Siquinelli

Posted on

7

Começando um projeto Web com TypeScript

Para começar um projeto do zero, simples, usando HTML, CSS, TypeScript e ESBuild.

Precisa fazer as seguintes etapas:

  1. Criar o diretório com o nome do seu projeto
  2. Criar o package.json
  3. Criar o tsconfig.json
  4. Instalar as dependências
    1. esbuild
    2. esbuild-serve
    3. typescript
    4. prettier
  5. Criar o diretório src
  6. Escrever o TypeScript inicial dentro de src
  7. Criar o diretório public/styles
  8. Escrever o HTML inicial dentro de public
  9. Escrever o CSS inicial dentro de public/styles
  10. Criar a configuração do ESBuild
  11. Criar a configuração do prettier
  12. Adicionar "type": "module" ao package.json
  13. Adicionar o script de build ao package.json
  14. Adicionar o script de start ao package.json
  15. Executar o npm start

Ou então compactar tudo isso em um script bash e usa-lo da seguinte forma

./create-project.sh meu-projeto
Enter fullscreen mode Exit fullscreen mode

Segue o código do script

#!/bin/bash
# Para usar, dê permissão de execução ao script
# usando o comando: chmod +x create-project.sh
# e então execute: ./create-project.sh projeto
mkdir $1
cd $1
npm init -y
echo '{
"compilerOptions": {
"target": "es5",
"lib": [
"es2020",
"dom",
"dom.iterable"
],
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": false,
"skipLibCheck": true
}
}' > tsconfig.json
npm i -D esbuild esbuild-serve typescript@latest prettier
mkdir src
echo "document.addEventListener('DOMContentLoaded', () => {
const form = document.querySelector('form')
if (form) {
const button = form.querySelector('button')
if (button) button.disabled = true
form.onchange = () => {
const valid = !form.checkValidity()
if (button) button.disabled = valid
}
form.onsubmit = (ev) => {
ev.preventDefault()
const data = new FormData(form)
const values = Object.fromEntries(data.entries())
console.log(values)
}
}
})
" > src/main.ts
mkdir -p public/styles
echo '<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;500&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="styles/main.css" />
<script src="main.js" defer></script>
<title>Página da Web</title>
</head>
<body>
<header>
<h1>'$1'</h1>
</header>
<main>
<article>
<h2>Artigo sobre JavaScript</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sin
laboramus, quis est, qui alienae modum statuat industriae? Traditur,
inquit, ab Epicuro ratio neglegendi doloris. Duo Reges: constructio
interrete. Te enim iudicem aequum puto, modo quae dicat ille bene
noris. Quamquam id quidem licebit iis existimare, qui legerint. Sed
quid sentiat, non videtis. Duo enim genera quae erant, fecit tria.
Quodsi ipsam honestatem undique pertectam atque absolutam. Odium autem
et invidiam facile vitabis. Consequens enim est et post oritur, ut
dixi.
</p>
<pre><code>document.addEventListener("DOMContentLoaded", () => {
const form = document.querySelector("form")
if (form) {
const button = form.querySelector("button")
if (button) button.disabled = true
form.onchange = () => {
const valid = !form.checkValidity()
if (button) button.disabled = valid
}
form.onsubmit = (ev) => {
ev.preventDefault()
const data = new FormData(form)
const values = Object.fromEntries(data.entries())
console.log(values)
}
}
})</code></pre>
</article>
<form>
<section>
<label for="name">Nome</label>
<input
id="name"
type="text"
autofocus
autocomplete="given-name"
name="name"
required
/>
<output>Obrigatório</output>
</section>
<section>
<label for="email">E-mail</label>
<input
id="email"
type="email"
name="email"
autocomplete="email"
required
/>
<output>Email inválido</output>
</section>
<section>
<label for="password">Senha</label>
<input
id="password"
type="password"
name="password"
autocomplete="new-password"
minlength="6"
required
/>
<output>Mínimo de 6 caracteres</output>
</section>
<section>
<label> <input type="checkbox" name="terms" /> Li e concordo com os termos </label>
</section>
<hr />
<button>Enviar</button>
</form>
</main>
<footer>&copy; 2021</footer>
</body>
</html>
' > public/index.html
echo ':root {
/* Palette generated by Material Palette
materialpalette.com/deep-purple/cyan */
--dark-primary-color: #512da8;
--default-primary-color: #673ab7;
--light-primary-color: #d1c4e9;
--text-primary-color: #ffffff;
--accent-color: #00bcd4;
--primary-text-color: #212121;
--secondary-text-color: #757575;
--divider-color: #bdbdbd;
--warn-color: #eb3535;
--default-font-family: "Fira Sans", sans-serif;
--default-element-margin: 6px;
--default-element-padding: 8px;
--default-block-padding: 10px;
--default-border-width: 2px;
--border-radius-xs: 2px;
--border-radius-sm: 4px;
--border-radius-md: 8px;
--border-radius-lg: 12px;
}
html,
body {
height: 100%;
}
body {
margin: 0;
display: flex;
flex-direction: column;
accent-color: var(--accent-color);
color: var(--primary-text-color);
font-family: var(--default-font-family);
}
main {
flex: 1;
padding: var(--default-block-padding);
}
header,
footer {
color: var(--text-primary-color);
padding: var(--default-block-padding);
background-color: var(--dark-primary-color);
}
button {
padding: var(--default-element-padding)
calc(var(--default-element-padding) * 2);
background-color: var(--default-primary-color);
border-radius: var(--border-radius-sm);
color: var(--text-primary-color);
border: 0;
}
button:disabled {
background-color: var(--light-primary-color);
}
button.accent {
background-color: var(--accent-color);
}
form section output {
visibility: hidden;
}
form.invalid input:invalid,
form section input:invalid:focus + output {
visibility: visible;
}
form section output {
color: var(--warn-color);
}
form section {
display: flex;
flex-direction: column;
margin-top: var(--default-element-margin);
margin-bottom: var(--default-element-margin);
}
input {
border-radius: var(--border-radius-sm);
padding: var(--default-element-padding);
border: var(--default-border-width) solid var(--dark-primary-color);
}
input[type="checkbox"] {
transform: scale(1.2);
}
pre {
padding: var(--default-block-padding);
background-color: var(--primary-text-color);
}
code {
font-size: 16px;
color: var(--light-primary-color);
}
' > public/styles/main.css
echo 'import esbuildServe from "esbuild-serve";
esbuildServe(
{
logLevel: "info",
entryPoints: ["src/main.ts"],
bundle: true,
outfile: "public/main.js",
sourcemap: true,
},
{ root: "public" }
);' > esbuild.config.js
echo '{
"semi": false,
"singleQuote": true
}' > .prettierrc
npx json -I -f package.json -e "this.type = 'module';"
npx json -I -f package.json -e "this.scripts.build = 'node esbuild.config.js';"
npx json -I -f package.json -e "this.scripts.start = 'node esbuild.config.js -w';"
npm start

Ele é extremamente simples e resolve o propósito com excelência.

Espero ter ajudado, até a próxima.
[]s

Image of Datadog

How to Diagram Your Cloud Architecture

Cloud architecture diagrams provide critical visibility into the resources in your environment and how they’re connected. In our latest eBook, AWS Solution Architects Jason Mimick and James Wenzel walk through best practices on how to build effective and professional diagrams.

Download the Free eBook

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay