Skip to content

Instantly share code, notes, and snippets.

@kstewart83
Created June 17, 2020 00:12
Show Gist options
  • Select an option

  • Save kstewart83/64277a2a0800fff13fa9e17b08eaf47b to your computer and use it in GitHub Desktop.

Select an option

Save kstewart83/64277a2a0800fff13fa9e17b08eaf47b to your computer and use it in GitHub Desktop.
Crank + Snowpack HMR
import * as Crank from '@bikeshaving/crank';
import { renderer as dom } from '@bikeshaving/crank/dom';
import { style } from 'typestyle';
const redMaker = { color: 'red' };
const bigFont = { fontSize: '30px' };
const bigRedClass = style(redMaker, bigFont);
declare global {
interface Window {
timer: number;
}
}
function Greeting({ name = 'World' }) {
return <div>Hello, {name}!!!!!</div>;
}
function* Timer(this: Crank.Context) {
let seconds: number;
if(window.timer === undefined) {
seconds = 0;
} else {
seconds = window.timer;
}
const interval = setInterval(() => {
seconds++;
window.timer = seconds;
this.refresh();
}, 1000);
try {
while (true) {
yield (
<div>
Seconds: {seconds}
</div>
);
}
} finally {
clearInterval(interval);
}
}
function* Counter(this: Crank.Context) {
let count = 0;
try {
while (true) {
count++;
yield (
<div>
You have updated this component {count}{' '}
{count === 1 ? ' time' : ' times'}
</div>
);
}
} finally {
console.log('Counter removed at count ', count);
}
}
async function QuoteOfTheDay() {
const res = await fetch("https://favqs.com/api/qotd");
const { quote } = await res.json();
return (
<p>
"{quote.body}" -- <a href={quote.url}>{quote.author}</a>
</p>
)
}
export async function *AsyncLabeledCounter (this: Crank.Context, {message}: {message: string}) {
let count = 0;
for await ({message} of this) {
yield <div>Loading...</div>;
await new Promise((resolve) => setTimeout(resolve, 2000));
count++;
yield <div>{message} {count}</div>
}
}
export function App(this: Crank.Context) {
return (
<Crank.Fragment>
<div class={bigRedClass}>Welcome!</div>
<button
onclick={() => {
this.refresh();
}}
>
Update
</button>
<Greeting />
<Greeting name="You"/>
<Counter />
<Timer />
<AsyncLabeledCounter message="The count is now: " />
<QuoteOfTheDay />
</Crank.Fragment>
);
}
export default App;
// @ts-ignore
if (import.meta.hot) {
// @ts-ignore
import.meta.hot.accept((module) => {
dom.render(
Crank.createElement(module.module.App),
document.getElementById('app') as HTMLDivElement,
);
});
/*
// @ts-ignore
import.meta.hot.dispose(() => {
});*/
}
// used in Snowpack pipeline to transform files on their way to the browser...see snowpack.config.json
module.exports = function createPlugin(snowpackConfig, pluginOptions) {
return {
async transform({ contents, urlPath, isDev }) {
if (
!isDev ||
!urlPath.endsWith('.js') ||
snowpackConfig.devOptions.hmr === false
) {
return;
}
if (
urlPath !== undefined &&
urlPath.startsWith('/_dist_/') &&
urlPath.slice(8, 9) === urlPath.slice(8, 9).toUpperCase()
) {
return {
result: `
${contents}
// HMR
console.log("${urlPath}");
(async () => {
var module = await import(${JSON.stringify(urlPath)});
console.log(module);
console.log(module.default);
console.log(module.default.toString());
console.log(Crank.createElement(module.default).tag);
// need API like Crank.hotswap(module.default);
})();
`,
};
}
return {
result: contents,
};
},
};
};
import confetti from 'canvas-confetti';
import * as Crank from "@bikeshaving/crank";
import { renderer as dom } from "@bikeshaving/crank/dom";
import App from './App';
confetti.create(null, {
resize: true,
useWorker: true,
})({ particleCount: 300, spread: 200, startVelocity: 60 });
dom.render(<App />, document.getElementById("app") as HTMLDivElement);
{
"name": "@snowpack/app-template-blank",
"version": "1.2.0",
"license": "MIT",
"keywords": [
"csa-template"
],
"publishConfig": {
"access": "public"
},
"scripts": {
"start": "snowpack dev",
"build": "snowpack build",
"format": "prettier --write \"src/**/*.js\"",
"lint": "prettier --check \"src/**/*.js\"",
"test": "echo \"This template does not include a test runner by default.\" && exit 1"
},
"dependencies": {
"@bikeshaving/crank": "^0.1.6",
"canvas-confetti": "^1.2.0",
"typescript": "^3.9.5",
"typestyle": "^2.1.0"
},
"devDependencies": {
"prettier": "^2.0.0",
"snowpack": "^2.5.0"
},
"gitHead": "795f4311d79a70cc9f19f21b512b7f8675d73f17"
}
{
"scripts": {
"mount:public": "mount public --to /",
"mount:src": "mount src --to /_dist_",
"build:tsx": "esbuild --jsx-factory=Crank.createElement --jsx-fragment=Crank.Fragment --loader=tsx"
},
"plugins": [
"./hmr.js"
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment