how to build a slide
😋 me 😙
contents
purpose
- manage with git
- share commonly used slides
- slides should be written in Markdown or HTML
- don't write JS as much as possible
- have a presenter note(optional)
🔧Tools🔨
Slide Framework
JavaScript
css
build flow⏳
Markdown -> HTML -> React
🤔
In this case, the loader chain is ...
markdown-loader -> html-loader
// webpack.config.js
{
test: /\.md$/,
use: [
'html-loader',
'markdown-loader'
]
}
fetch slides
The slide file name is 0-title.md, 01-context.md, 02-dir/0-title.md, etc...
// fetch all slides
const context = require.context('./slides', true, /(md|html)$/);
const res = {
id : context.id,
slides: context
.keys()
.sort() // sort by file name
.map((e) => context(e))
};
require.context
is provided by webpack.
The content acquired by the path is expanded as a string by require.context
.
send to a react component
Pass slides to React using dangerouslySetInnerHTML
after slides are converted to HTML.
const Base = (props) => (
<article>
{
props.slides.map((slide, i) => (
<section
key={slide.meta.id}
className={slide.meta.className}
data-bespoke-backdrop={slide.meta.background}
dangerouslySetInnerHTML={{ __html: slide.context }}
/>
))
}
</article>
);
production🚀
Service Worker
Introduce offline-plugin to use Service Worker.
Save scripts and images preferentially.
// webpack.prod.config.js
module.exports = {
plugins: [
new OfflinePlugin(),
...
]
};
// offline.js
import offlineRuntime from 'offline-plugin/runtime';
offlineRuntime.install();
Service Worker
dynamic import
Don't bundle with 1 file.
Presenter Mode's codes are separated from the core code.
// AppContainer.js
constructor(props) {
if (mode === 'view') {
import(/* webpackChunkName: 'presenter.view' */ './ContentView/View')
.then((e) => {
...
});
}
else if (mode === 'host') {
import(/* webpackChunkName: 'presenter.host' */ './ContentView/Host')
.then((e) => {
...
});
}
}
https://github.com/abouthiroppy/slides/blob/master/src/lib/AppContainer.js
dynamic import
Dynamic Import is currently in stage 3 of the TC39 process.
They are divided by webpack.
Hash: 08e7000cd507fa241759
Time: 77409ms
Asset Size Chunks Chunk Names
0.08e7000cd507fa241759.js 14.4 kB 0 [emitted]
1.08e7000cd507fa241759.js 3.65 kB 1 [emitted] presenter.host
2.08e7000cd507fa241759.js 1.45 kB 2 [emitted] presenter.view
08e7000cd507fa241759.js 1.27 MB 3 [emitted] [big] main
reduce image size
Use image-webpack-loader, it uses imagemin.
image-webpack-loader -> file-loader
// webpack.config.js
{
test: /\.(png|jpg|gif|svg?)$/,
use: [
'file-loader',
'image-webpack-loader'
]
}
Presenter Mode 🎬
Presenter Mode
Presenter Mode is very simple, it has only a next slide view and note.
how to share page information
Use localStorage to talk in real time between Host and View.
// host.js
window.slide.bespoke.on('activate', (e) => {
localStorage.setItem('page', JSON.stringify({
date: Date.now(),
page: e.index
}));
});
// view.js
window.addEventListener('storage', (e) => {
if (e.key === 'page') {
const page = JSON.parse(e.newValue).page;
window.slide.bespoke.slide(page);
}
});
https://github.com/abouthiroppy/slides/tree/master/src/lib/ContentView
INFORMATION 💁
NODE FESTIVAL IN TOKYO🗼
largest Node.js and JavaScript conference in Japan!!!