Your Code
The browser
The user
npm install lodash
const lodash = require('lodash')
that looks nice!
DX
UX
DX
UX
npm install lodash
const lodash = require('lodash')
THIS IS SO EASY!
npm run build
npm install lodash
const lodash = require('lodash')
No visible cost
npm run build
But most of us aren’t making Figma. Most of us are still making documents [...].
Jason Godesky
https://scribe.rip/@jason.godesky/when-javascript-fails-52eef47e90db
The browser (and the user)
The browser (and the user)
Your framework
Your frameworks' dependencies
The browser (and the user)
A library from npm
The browser (and the user)
Your code.
The browser (and the user)
Dependencies, complexities and abstractions
Third party dependencies
Complexity
Third party dependencies
Complexity
Third party dependencies
Complexity
UX
the thing that’s really bugged me for the past decade is the increasing complexity of “modern” frontend development when it isn’t driven by user needs
Jeremy Keith
https://pixelpioneers.co/blog/2023/speaker-spotlight-jeremy-keith
2
https://www.theregister.com/2016/03/23/npm_left_pad_chaos/
becomes unmaintained on GitHub
has security vulnerability that no one is fixing
has bad perf case that your
website exposes
{
{
Every dependency you add to a project is one more potential single point of failure.
Jeremy Keith
https://adactio.com/journal/19021
Your code
Mission critical abstractions and dependencies
use the platform
jackfranklin.co.uk/blog/working-with-react-and-the-web-platform/
custom elements
HTML Form Validation
FormData API
Constraint Validation API
98%
96%
97%
data from caniuse.com on 28/04/2023
npm install event-emitter
Well I'd just use EventTarget
class BlogPostComments extends EventTarget {
onUpdate() {
this.dispatchEvent(new Event('updatedcomments'));
}
}
const comments = new BlogPostComments();
comments.addEventListener('updatedcomments', () => {
// we got some new comments!
});
class BlogPostComments extends EventTarget {
onUpdate() {
this.dispatchEvent(new Event('updatedcomments'));
}
}
const comments = new BlogPostComments();
comments.addEventListener('updatedcomments', () => {
// we got some new comments!
});
97%
https://caniuse.com/mdn-api_eventtarget
You can’t JavaScript your way out of an excess-JavaScript problem. These large JavaScript bundles are costly to site performance.
Zach Leat
https://www.zachleat.com/web/single-page-applications/
I have a problem to solve
what dependency will solve this for me?
npm install lodash
const lodash = require('lodash')
This is so easy!
npm run build
The problem with conveniences is that they come at a cost. How easy is it to add this one little convenience that will surely make our lives better, never think about it again and move on.
Pascal Schilp
https://dev.to/thepassle/the-cost-of-convenience-kco
I have a problem to solve
Does the browser provide a solution natively?
Does the browser provide a solution natively?
No: I need to implement or add a dependency
Yes!
https://twitter.com/ksylor/status/1456341818698838016
The general idea of an “Islands” architecture is deceptively simple: render HTML pages on the server, and inject placeholders or slots around highly dynamic region
Jason Miller
https://jasonformat.com/islands-architecture/
Jake Archibald
https://twitter.com/jaffathecake/status/1448585986422808576
This means I can enhance little parts of the page without going all-in on a framework.
this.user = 'jack';
this.render();
this.user = 'jack';
this.render();
const [
user,
setUser
] = useState('');
setState('jack');
this.user = 'jack';
this.render();
const [
user,
setUser
] = useState('');
setState('jack');
Libraries and a frameworks can be distinguished by looking at the Inversion of Control
Surma
https://surma.dev/things/cost-of-convenience/index.html
Use framework primitive to update data
Framework re-renders for you.
Render component
Use framework primitive to update data
Framework re-renders for you.
Render component
Update legacy jQuery component
However, as frameworks often put themselves at the core of any architecture, it can be hard to opt out
Surma
https://surma.dev/things/cost-of-convenience/index.html
1. more code in your website's bundle
3. another thing to upgrade (or not) on a semi-regular basis
2. another potential point of failure
4. more complexity and code to understand
Was £299, now £49 for TODAY ONLY!!!!
is this dependency providing?
would it be like to build it ourselves?
do we do if it becomes unmaintained?
is its impact on the bundle size?
if we have to replace it?
LitElement vs lit-html
CodeMirror vs in-house
Me! (is it weird to quote your blog posts in talks? Maybe. Egotistical? Definitely...)
https://www.jackfranklin.co.uk/blog/check-in-your-node-dependencies/
No more npm install locally or on CI bots
100% reproducible builds by default
No blocked builds if npm is down
Dependencies of dependencies are no longer invisible
You are forced to see the code you are committing.
Dependency update code changes are unmissable
no more energy used from npm installs
30 engineers with 100s of builds per day...
node_modules/*
!node_modules/new-dep
It fucks me up, we devops / sre do our best to advocate for good tools, do our best to educate people, and there's a dude coming from google saying "oh yeah no more npm installs" and i want to fucking cry
warning: approach may make you unpopular
The browser (and the user)
Large framework
The browser (and the user)
web components
Historically, it has been difficult to use Shadow DOM in combination with Server-Side Rendering because there was no built-in way to express Shadow Roots in the server-generated HTML
Jason Miller, Mason Freed
https://developer.chrome.com/en/articles/declarative-shadow-dom/
Single Page Application advocates argue [...]. While we can debate those points (recognizing also that they will fade into irrelevance as the web platform progresses)
Zach Leat
https://www.zachleat.com/web/single-page-applications/
⏰
KnockoutJS
Backbone
⏰
KnockoutJS
Backbone
Angular 1 & Object.observe()
⏰
KnockoutJS
Backbone
Angular 1 & Object.observe()
React
Vue
⏰
KnockoutJS
Backbone
Angular 1 & Object.observe()
React
Vue
React hooks
Svelte
⏰
KnockoutJS
Backbone
Angular 1 & Object.observe()
React
Vue
React hooks
Svelte
web-components, Lit, Stencil, islands
⏰
KnockoutJS
Backbone
Angular 1 & Object.observe()
React
Vue
React hooks
Svelte
web-components, Lit, Stencil, islands
what is next?
??
* in this slide Jack of the future is played by Jack's dad
What can I do today?
To make the future maintainers happy?
A website that uses standard HTML links for navigation is easier for assistive technologies and web crawlers to use.
[...]
Jason Miller
https://jasonformat.com/islands-architecture/
The browser (and the user)
Framework internals
Core framework
The browser (and the user)
Framework internals
Core framework
you find yourself having outgrown the framework [...], and you want to switch. This can be really hard, because frameworks shape your code, and each framework is different, so there is no easy migration path
Surma
https://surma.dev/things/cost-of-convenience/index.html
The browser (and the user)
Your code.
Shrink this
The browser (and the user)
to this
DX
UX
DX
UX
DX
UX
jackf.io/talks/abstractions
jackf.io/toot
jackf.io/tweet
jackf.io/blog