Skip to content

Commit

Permalink
copy preact example from vercel/vercel (#1025)
Browse files Browse the repository at this point in the history
  • Loading branch information
erikareads authored Jan 13, 2025
1 parent 3fc880b commit 873a431
Show file tree
Hide file tree
Showing 28 changed files with 11,912 additions and 0 deletions.
7 changes: 7 additions & 0 deletions framework-boilerplates/preact/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules
/build
/*.log
.env
.env.build

.vercel
30 changes: 30 additions & 0 deletions framework-boilerplates/preact/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Preact

This directory is a brief example of a [Preact](https://preactjs.com/) app that can be deployed to Vercel with zero configuration.

## Deploy Your Own

Deploy your own Preact project with Vercel.

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/examples/tree/main/framework-boilerplates/preact&template=preact)

_Live Example: https://preact-template.vercel.app_

## Running Locally

``` bash
# install dependencies
npm install

# serve with hot reload at localhost:8080
npm run dev

# build for production with minification
npm run build

# test the production build locally
npm run serve

# run tests with jest and enzyme
npm run test
```
41 changes: 41 additions & 0 deletions framework-boilerplates/preact/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"private": true,
"scripts": {
"build": "NODE_OPTIONS=--openssl-legacy-provider preact build",
"serve": "sirv build --port 8080 --cors --single",
"dev": "preact watch",
"lint": "eslint src",
"test": "jest"
},
"engines": {
"node": "18.x"
},
"eslintConfig": {
"extends": "preact",
"ignorePatterns": [
"build/"
]
},
"devDependencies": {
"enzyme": "^3.11.0",
"enzyme-adapter-preact-pure": "^4.1.0",
"eslint": "^8.41.0",
"eslint-config-preact": "^1.3.0",
"jest": "^29.5.0",
"jest-preset-preact": "^4.0.4",
"preact-cli": "^3.4.5",
"sirv-cli": "2.0.2"
},
"dependencies": {
"preact": "^10.15.0",
"preact-render-to-string": "6.0.3",
"preact-router": "^4.1.1"
},
"jest": {
"preset": "jest-preset-preact",
"setupFiles": [
"<rootDir>/tests/__mocks__/browserMocks.js",
"<rootDir>/tests/__mocks__/setupTests.js"
]
}
}
1 change: 1 addition & 0 deletions framework-boilerplates/preact/size-plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"timestamp":1642471583231,"files":[{"filename":"ssr-build/ssr-bundle.43203.css","previous":569,"size":0,"diff":-569},{"filename":"ssr-build/ssr-bundle.js","previous":4555,"size":0,"diff":-4555},{"filename":"bundle.4922e.css","previous":0,"size":447,"diff":447},{"filename":"bundle.*****.esm.js","previous":0,"size":8322,"diff":8322},{"filename":"polyfills.*****.esm.js","previous":0,"size":2191,"diff":2191},{"filename":"route-home.chunk.8aeee.css","previous":0,"size":75,"diff":75},{"filename":"route-home.chunk.*****.esm.js","previous":0,"size":252,"diff":252},{"filename":"route-profile.chunk.141aa.css","previous":0,"size":78,"diff":78},{"filename":"route-profile.chunk.*****.esm.js","previous":0,"size":1137,"diff":1137},{"filename":"sw-esm.js","previous":0,"size":10767,"diff":10767},{"filename":"sw.js","previous":0,"size":10762,"diff":10762},{"filename":"bundle.8eca2.js","previous":0,"size":8369,"diff":8369},{"filename":"polyfills.03377.js","previous":0,"size":2291,"diff":2291},{"filename":"route-home.chunk.732e3.js","previous":0,"size":256,"diff":256},{"filename":"route-profile.chunk.6a5ba.js","previous":0,"size":1625,"diff":1625},{"filename":"index.html","previous":0,"size":1045,"diff":1045},{"filename":"200.html","previous":0,"size":645,"diff":645}]}]
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions framework-boilerplates/preact/src/components/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { h } from 'preact';
import { Router } from 'preact-router';

import Header from './header';

// Code-splitting is automated for `routes` directory
import Home from '../routes/home';
import Profile from '../routes/profile';

const App = () => (
<div id="app">
<Header />
<Router>
<Home path="/" />
<Profile path="/profile/" user="me" />
<Profile path="/profile/:user" />
</Router>
</div>
)

export default App;
16 changes: 16 additions & 0 deletions framework-boilerplates/preact/src/components/header/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { h } from 'preact';
import { Link } from 'preact-router/match';
import style from './style.css';

const Header = () => (
<header class={style.header}>
<h1>Preact App</h1>
<nav>
<Link activeClassName={style.active} href="/">Home</Link>
<Link activeClassName={style.active} href="/profile">Me</Link>
<Link activeClassName={style.active} href="/profile/john">John</Link>
</nav>
</header>
);

export default Header;
48 changes: 48 additions & 0 deletions framework-boilerplates/preact/src/components/header/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.header {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 56px;
padding: 0;
background: #673AB7;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
z-index: 50;
}

.header h1 {
float: left;
margin: 0;
padding: 0 15px;
font-size: 24px;
line-height: 56px;
font-weight: 400;
color: #FFF;
}

.header nav {
float: right;
font-size: 100%;
}

.header nav a {
display: inline-block;
height: 56px;
line-height: 56px;
padding: 0 15px;
min-width: 50px;
text-align: center;
background: rgba(255,255,255,0);
text-decoration: none;
color: #FFF;
will-change: background-color;
}

.header nav a:hover,
.header nav a:active {
background: rgba(0,0,0,0.2);
}

.header nav a.active {
background: rgba(0,0,0,0.4);
}
4 changes: 4 additions & 0 deletions framework-boilerplates/preact/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import './style';
import App from './components/app';

export default App;
21 changes: 21 additions & 0 deletions framework-boilerplates/preact/src/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "my-project",
"short_name": "my-project",
"start_url": "/",
"display": "standalone",
"orientation": "portrait",
"background_color": "#fff",
"theme_color": "#673ab8",
"icons": [
{
"src": "/assets/icons/android-chrome-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/assets/icons/android-chrome-512x512.png",
"type": "image/png",
"sizes": "512x512"
}
]
}
11 changes: 11 additions & 0 deletions framework-boilerplates/preact/src/routes/home/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { h } from 'preact';
import style from './style.css';

const Home = () => (
<div class={style.home}>
<h1>Home</h1>
<p>This is the Home component.</p>
</div>
);

export default Home;
5 changes: 5 additions & 0 deletions framework-boilerplates/preact/src/routes/home/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.home {
padding: 56px 20px;
min-height: 100%;
width: 100%;
}
31 changes: 31 additions & 0 deletions framework-boilerplates/preact/src/routes/profile/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { h } from 'preact';
import {useEffect, useState} from "preact/hooks";
import style from './style.css';

// Note: `user` comes from the URL, courtesy of our router
const Profile = ({ user }) => {
const [time, setTime] = useState(Date.now());
const [count, setCount] = useState(10);

useEffect(() => {
let timer = setInterval(() => setTime(Date.now()), 1000);
return () => clearInterval(timer);
}, []);

return (
<div class={style.profile}>
<h1>Profile: {user}</h1>
<p>This is the user profile for a user named { user }.</p>

<div>Current time: {new Date(time).toLocaleString()}</div>

<p>
<button onClick={() => setCount((count) => count + 1)}>Click Me</button>
{' '}
Clicked {count} times.
</p>
</div>
);
}

export default Profile;
5 changes: 5 additions & 0 deletions framework-boilerplates/preact/src/routes/profile/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.profile {
padding: 56px 20px;
min-height: 100%;
width: 100%;
}
20 changes: 20 additions & 0 deletions framework-boilerplates/preact/src/style/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
html, body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
background: #FAFAFA;
font-family: 'Helvetica Neue', arial, sans-serif;
font-weight: 400;
color: #444;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

* {
box-sizing: border-box;
}

#app {
height: 100%;
}
4 changes: 4 additions & 0 deletions framework-boilerplates/preact/src/sw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { getFiles, setupPrecaching, setupRouting } from 'preact-cli/sw/';

setupRouting();
setupPrecaching(getFiles());
15 changes: 15 additions & 0 deletions framework-boilerplates/preact/src/template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title><% preact.title %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-icon" href="/assets/icons/apple-touch-icon.png">
<% preact.headEnd %>
</head>
<body>
<% preact.bodyEnd %>
</body>
</html>
21 changes: 21 additions & 0 deletions framework-boilerplates/preact/tests/__mocks__/browserMocks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Mock Browser API's which are not supported by JSDOM, e.g. ServiceWorker, LocalStorage
/**
* An example how to mock localStorage is given below 👇
*/

/*
// Mocks localStorage
const localStorageMock = (function() {
let store = {};
return {
getItem: (key) => store[key] || null,
setItem: (key, value) => store[key] = value.toString(),
clear: () => store = {}
};
})();
Object.defineProperty(window, 'localStorage', {
value: localStorageMock
}); */
3 changes: 3 additions & 0 deletions framework-boilerplates/preact/tests/__mocks__/fileMocks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This fixed an error related to the CSS and loading gif breaking my Jest test
// See https://facebook.github.io/jest/docs/en/webpack.html#handling-static-assets
module.exports = 'test-file-stub';
6 changes: 6 additions & 0 deletions framework-boilerplates/preact/tests/__mocks__/setupTests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-preact-pure';

configure({
adapter: new Adapter()
});
12 changes: 12 additions & 0 deletions framework-boilerplates/preact/tests/header.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { h } from 'preact';
import Header from '../src/components/header';
// See: https://github.com/preactjs/enzyme-adapter-preact-pure
import { shallow } from 'enzyme';

describe('Initial Test of the Header', () => {
test('Header renders 3 nav items', () => {
const context = shallow(<Header />);
expect(context.find('h1').text()).toBe('Preact App');
expect(context.find('Link').length).toBe(3);
});
});
Loading

0 comments on commit 873a431

Please sign in to comment.