Skip to content

Commit 836c591

Browse files
committed
Refactors p5.js plugin for improved performance and loading
Performance improvements Initial JS payload on the home page dropped from the old 1.2 MB entry bundle (/_nuxt/-fb-QVTY.js, 346 KB gzip) to a 215 KB entry chunk (/_nuxt/ COl_3hmy.js, 79 KB gzip). That’s roughly ‑82 % raw (‑77 % gzip) for the blocking script download on first paint. The heavy p5 chunk (≈1.0 MB raw / 267 KB gzip) is no longer module-preloaded. It now arrives only as a low-priority prefetch and is actually executed only when a playground page calls $p5(), so non-3D pages avoid paying that cost at all.
1 parent 21a5dce commit 836c591

9 files changed

Lines changed: 153 additions & 53 deletions

File tree

components/ModelPreview.global.vue

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,89 @@
11
<template>
2-
<div id="canvas" class="h-64" />
2+
<div ref="container" class="h-64" />
33
</template>
44

55
<script setup lang="ts">
6-
const { $p5 } = useNuxtApp();
6+
import { onBeforeUnmount, onMounted, ref } from "vue";
77
8-
const { path, backgroundColor = 100 } = defineProps<{
9-
path: string;
10-
backgroundColor?: Number;
11-
}>();
8+
const props = withDefaults(
9+
defineProps<{
10+
path: string;
11+
backgroundColor?: number;
12+
}>(),
13+
{
14+
backgroundColor: 100,
15+
},
16+
);
1217
13-
onMounted(() => {
14-
console.log(backgroundColor);
15-
const sketch = (s) => {
16-
const c = document.getElementById("canvas");
18+
const container = ref<HTMLElement | null>(null);
19+
let p5Instance: any = null;
1720
18-
const WIDTH = c.clientWidth;
19-
const HEIGHT = c.clientHeight;
21+
onMounted(async () => {
22+
if (!container.value) {
23+
return;
24+
}
2025
26+
const { $p5 } = useNuxtApp();
27+
const p5 = await $p5();
28+
const host = container.value;
29+
30+
const sketch = (s: any) => {
2131
let model;
22-
let angle;
32+
let angle = 0;
2333
let rotate = true;
2434
35+
const getSize = () => {
36+
return {
37+
width: host.clientWidth || 0,
38+
height: host.clientHeight || 0,
39+
};
40+
};
41+
2542
s.preload = () => {
26-
model = s.loadModel(path, true);
43+
model = s.loadModel(props.path, true);
2744
};
2845
2946
s.setup = () => {
30-
s.createCanvas(WIDTH, HEIGHT, s.WEBGL);
47+
const { width, height } = getSize();
48+
s.createCanvas(width, height, s.WEBGL);
49+
};
50+
51+
s.windowResized = () => {
52+
const { width, height } = getSize();
53+
s.resizeCanvas(width, height);
3154
};
3255
3356
s.mouseClicked = () => {
3457
rotate = false; // disable object rotation on click
3558
};
3659
3760
s.draw = () => {
38-
s.background(backgroundColor);
61+
const bg = Number(props.backgroundColor ?? 100);
62+
63+
s.background(bg);
3964
s.lights();
4065
4166
if (rotate) {
4267
angle = s.frameCount * 0.005;
4368
}
69+
4470
s.rotateX(angle);
4571
s.rotateY(angle);
4672
s.orbitControl();
4773
48-
s.model(model);
74+
if (model) {
75+
s.model(model);
76+
}
4977
};
5078
};
5179
52-
// eslint-disable-next-line no-new
53-
new $p5(sketch, "canvas");
80+
p5Instance = new p5(sketch, host);
81+
});
82+
83+
onBeforeUnmount(() => {
84+
if (p5Instance) {
85+
p5Instance.remove?.();
86+
p5Instance = null;
87+
}
5488
});
5589
</script>

components/playground/Wave.vue

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,14 @@ export default {
3131
default: 266,
3232
},
3333
},
34-
mounted() {
34+
data() {
35+
return {
36+
p5Instance: null,
37+
};
38+
},
39+
async mounted() {
40+
const p5 = await this.$p5();
41+
3542
const sketch = (s) => {
3643
const HEIGHT = s.windowWidth >= 450 ? this.canvasHeight : 200;
3744
const WIDTH = s.windowWidth >= 450 ? 800 : 300;
@@ -87,11 +94,11 @@ export default {
8794
};
8895
};
8996
90-
// eslint-disable-next-line no-new
91-
new this.$p5(sketch, this.id);
97+
this.p5Instance = new p5(sketch, this.id);
9298
},
93-
data() {
94-
return {};
99+
beforeUnmount() {
100+
this.p5Instance?.remove?.();
101+
this.p5Instance = null;
95102
},
96103
};
97104
</script>

pages/playground/palettes/mountains.vue

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
<div class="m-6 grid h-2/3 place-items-center">
44
<div class="font-mono text-white">
55
<ClientOnly>
6-
<div id="canvas" class="mb-2 h-96 border-2 border-white" />
6+
<div
7+
ref="canvas"
8+
id="canvas"
9+
class="mb-2 h-96 border-2 border-white"
10+
></div>
711
<template #fallback>
812
<div
913
class="mb-2 flex h-96 items-center justify-center border-2 border-white bg-gray-800"
@@ -24,13 +28,27 @@
2428
definePageMeta({ layout: "light" });
2529
export default {
2630
data() {
27-
return {};
31+
return {
32+
p5Instance: null,
33+
};
2834
},
29-
mounted() {
35+
async mounted() {
36+
await this.$nextTick();
37+
38+
let canvas = this.$refs.canvas;
39+
if (!canvas) {
40+
await this.$nextTick();
41+
canvas = this.$refs.canvas;
42+
}
43+
if (!(canvas instanceof HTMLElement)) {
44+
console.warn("Mountains palette: canvas container not found");
45+
return;
46+
}
47+
3048
// There is a bug where multiple p5 canvases are created within canvas div if a
3149
// user closely and re-opens the palettes playground. This is a workaround to
3250
// remove the children canvas elements within this div.
33-
document.getElementById("canvas").textContent = "";
51+
canvas.textContent = "";
3452
3553
const PALETTE = [
3654
"#FFBA08",
@@ -47,9 +65,8 @@ export default {
4765
4866
const sketch = (s) => {
4967
// canvas dimensions
50-
const c = document.getElementById("canvas");
51-
const WIDTH = c.clientWidth;
52-
const HEIGHT = c.clientHeight;
68+
const WIDTH = canvas.clientWidth;
69+
const HEIGHT = canvas.clientHeight;
5370
5471
const waves = [
5572
{ color: PALETTE[1], min: 0, max: 0.2, yoff: 2.0 },
@@ -104,8 +121,12 @@ export default {
104121
};
105122
};
106123
107-
// eslint-disable-next-line no-new
108-
new this.$p5(sketch, "canvas");
124+
const p5 = await this.$p5();
125+
this.p5Instance = new p5(sketch, canvas);
126+
},
127+
beforeUnmount() {
128+
this.p5Instance?.remove?.();
129+
this.p5Instance = null;
109130
},
110131
};
111132
</script>

pages/playground/palettes/variance.vue

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
definePageMeta({ layout: "light" });
2222
export default {
2323
data() {
24-
return {};
24+
return {
25+
p5Instance: null,
26+
};
2527
},
26-
mounted() {
28+
async mounted() {
2729
const PALETTE = [
2830
"#FFBA08",
2931
"#FAA307",
@@ -88,8 +90,12 @@ export default {
8890
};
8991
};
9092
91-
// eslint-disable-next-line no-new
92-
new this.$p5(sketch, "canvas");
93+
const p5 = await this.$p5();
94+
this.p5Instance = new p5(sketch, "canvas");
95+
},
96+
beforeUnmount() {
97+
this.p5Instance?.remove?.();
98+
this.p5Instance = null;
9399
},
94100
};
95101
</script>

pages/playground/plotter/index.vue

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ export default {
113113
startingX: 125,
114114
startingY: 150,
115115
startingAngle: 0,
116+
p5Instance: null,
116117
sequence:
117118
"3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678",
118119
@@ -183,7 +184,7 @@ export default {
183184
s.endShape();
184185
},
185186
},
186-
mounted() {
187+
async mounted() {
187188
// dynamically set canvas width and height based on div size
188189
const c = document.getElementById("canvas-container");
189190
this.width = c.clientWidth;
@@ -200,8 +201,12 @@ export default {
200201
};
201202
};
202203
203-
// eslint-disable-next-line no-new
204-
new this.$p5(sketch, "canvas");
204+
const p5 = await this.$p5();
205+
this.p5Instance = new p5(sketch, "canvas");
206+
},
207+
beforeUnmount() {
208+
this.p5Instance?.remove?.();
209+
this.p5Instance = null;
205210
},
206211
};
207212
</script>

pages/playground/tiling/index.vue

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,13 @@ definePageMeta({ layout: "light" });
106106
107107
export default {
108108
data() {
109-
return {};
109+
return {
110+
p5Instance: null,
111+
};
110112
},
111-
mounted() {
113+
async mounted() {
114+
const p5 = await this.$p5();
115+
112116
const sketch = (s) => {
113117
const HEIGHT = 500;
114118
const WIDTH = 500;
@@ -175,8 +179,11 @@ export default {
175179
};
176180
};
177181
178-
// eslint-disable-next-line no-new
179-
new this.$p5(sketch, "canvas");
182+
this.p5Instance = new p5(sketch, "canvas");
183+
},
184+
beforeUnmount() {
185+
this.p5Instance?.remove?.();
186+
this.p5Instance = null;
180187
},
181188
};
182189
</script>

plugins/p5.client.js

Lines changed: 0 additions & 9 deletions
This file was deleted.

plugins/p5.client.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
let p5Promise: Promise<any> | null = null;
2+
3+
export default defineNuxtPlugin(() => {
4+
const loadP5 = async () => {
5+
if (!p5Promise) {
6+
p5Promise = import("p5").then((mod) => mod.default ?? mod);
7+
}
8+
return p5Promise;
9+
};
10+
11+
return {
12+
provide: {
13+
p5: loadP5,
14+
},
15+
};
16+
});

types/p5.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
declare module '#app' {
2+
interface NuxtApp {
3+
$p5: () => Promise<any>;
4+
}
5+
}
6+
7+
declare module 'vue' {
8+
interface ComponentCustomProperties {
9+
$p5: () => Promise<any>;
10+
}
11+
}
12+
13+
export {};

0 commit comments

Comments
 (0)