Để tiếp nối bài viết về Svelte. Trong bài này, chúng ta hãy cùng tìm hiểu về Sapper. Đây chính là framework của Svelte.
Đầu tiên là Cấu trúc thư mục của 1 Sapper project. Chúng ta sẽ đi tìm hiểu cấu trúc này và xem Sapper liệu có gì hay ho không nhé
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ├ package.json ├ src │ ├ routes │ │ ├ # your routes here │ │ ├ _error.svelte │ │ └ index.svelte │ ├ client.js │ ├ server.js │ ├ service-worker.js │ └ template.html ├ static │ ├ # your files here └ rollup.config.js / webpack.config.js |
1. package.json
Tương tự Vue, React, đây là file config các thư viện cần sử dụng.
Lưu ý: Thêm dòng "private": true
vào file để sửa warning package.json: No license field
.
2. src
src/client.js
File này sẽ import thư việnsapper
để sử dụng cho web
1 2 3 4 5 6 | <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> sapper <span class="token keyword">from</span> <span class="token string">'@sapper/app'</span><span class="token punctuation">;</span> sapper<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">{</span> target<span class="token operator">:</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#sapper'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Các hàm api client sapper gồm:
start({ target })
- target – một page element
- return Promise
Hàm config router và starts the app – lắng nghe các sự kiện của thẻ <a>, interacts với history API, render và updates các components.
Ví dụ
12345678<span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> sapper <span class="token keyword">from</span> <span class="token string">'@sapper/app'</span><span class="token punctuation">;</span>sapper<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">{</span>target<span class="token operator">:</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#sapper'</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'client-side app has started'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>goto(href, options?)
- href — the page to go to
- options — not required
Hàm xử lý điều hướng trang khi người dùng click vào thẻ <a> có href tương ứng và trả về một Promise
1234567891011<span class="token keyword">import</span> <span class="token punctuation">{</span> goto <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@sapper/app'</span><span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token function-variable function">navigateAndSave</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token keyword">await</span> <span class="token function">goto</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">saveItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">const</span> <span class="token function-variable function">saveItem</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token comment">// do something with the database</span><span class="token punctuation">}</span>prefetch(href)
- href — the page to prefetch
Prefetch trang khi người dùng click phần tử <a> có
rel=prefetch
.prefetchRoutes(routes?)
- routes — an optional array of strings representing routes to prefetch
src/server.js
File này sẽ xử lý việc connect web với server.
Sapper sử dụng thư viện Polka, là một native HTTP server, tương tự như axios, thư viện này sẽ hộ trợ việc gọi api bên phía server.
Ví dụ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">polka</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token string">'Hello world!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/users'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token string">'Get all users!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/users'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token string">'Create a new User!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">'/users/:id'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Update User with ID of </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>req<span class="token punctuation">.</span>params<span class="token punctuation">.</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token string">'/users/:id'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"><a href="/cdn-cgi/l/email-protection" class="__cf_email__">[email protected]</a> User </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>req<span class="token punctuation">.</span>params<span class="token punctuation">.</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">!</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
template.html
Đây là một file template cho response trả về từ phía server. Sapper sẽ inject content vào trong file khi có response trả về.
src/routes
Khác với Vue, React, đây là thư mục gồm các trang của ứng dụng. Route được định nghĩa bởi cấu trúc và filename của các pages.
3. stattic
Folder chứa các file bất kì, như images, favicon,…
4. rollup.config.js / webpack.config.js
Đây là file cấu hình ứng dụng, tương tự Vue và React
5. Systax Svelte component
Mỗi svelte component cho gồm 3 phần:
- code elements
- code style: khai báo bằng thẻ <style>
- code script: Khai báo bằng thẻ <script>
Cấu trúc 1 file svelte tương tự Vue, tuy nhiên, svelte k cần khai báo element trong thẻ <template> như Vue
Ví dụ:
1 2 3 4 5 6 | <span class="token operator"><</span>svelte<span class="token operator">:</span>head<span class="token operator">></span> <span class="token operator"><</span>title<span class="token operator">></span>Welcome<span class="token operator"><</span><span class="token operator">/</span>title<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>svelte<span class="token operator">:</span>head<span class="token operator">></span> <span class="token operator"><</span>h1<span class="token operator">></span>Hello and welcome to my site<span class="token operator">!</span><span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span> src<span class="token operator">/</span>routes<span class="token operator">/</span>blog<span class="token operator">/</span><span class="token punctuation">[</span>slug<span class="token punctuation">]</span><span class="token punctuation">.</span>svelte <span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>script context<span class="token operator">=</span><span class="token string">"module"</span><span class="token operator">></span> <span class="token comment">// the (optional) preload function takes a</span> <span class="token comment">// `{ path, params, query }` object and turns it into</span> <span class="token comment">// the data we need to render the page</span> <span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">preload</span><span class="token punctuation">(</span><span class="token parameter">page<span class="token punctuation">,</span> session</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// the `slug` parameter is available because this file</span> <span class="token comment">// is called [slug].svelte</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> slug <span class="token punctuation">}</span> <span class="token operator">=</span> page<span class="token punctuation">.</span>params<span class="token punctuation">;</span> <span class="token comment">// `this.fetch` is a wrapper around `fetch` that allows</span> <span class="token comment">// you to make credentialled requests on both</span> <span class="token comment">// server and client</span> <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">fetch</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">blog/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>slug<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.json</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> article <span class="token operator">=</span> <span class="token keyword">await</span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> article <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>script<span class="token operator">></span> <span class="token operator"><</span>script<span class="token operator">></span> <span class="token keyword">export</span> <span class="token keyword">let</span> article<span class="token punctuation">;</span> <span class="token operator"><</span><span class="token operator">/</span>script<span class="token operator">></span> <span class="token operator"><</span>style<span class="token operator">></span> div <span class="token punctuation">{</span> color<span class="token operator">:</span> purple<span class="token punctuation">;</span> font<span class="token operator">-</span>family<span class="token operator">:</span> <span class="token string">'Comic Sans MS'</span><span class="token punctuation">,</span> cursive<span class="token punctuation">;</span> font<span class="token operator">-</span>size<span class="token operator">:</span> <span class="token number">2</span>em<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>style<span class="token operator">></span> <span class="token operator"><</span>svelte<span class="token operator">:</span>head<span class="token operator">></span> <span class="token operator"><</span>title<span class="token operator">></span><span class="token punctuation">{</span>article<span class="token punctuation">.</span>title<span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>title<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>svelte<span class="token operator">:</span>head<span class="token operator">></span> <span class="token operator"><</span>h1<span class="token operator">></span><span class="token punctuation">{</span>article<span class="token punctuation">.</span>title<span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>div <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">'content'</span><span class="token operator">></span> <span class="token punctuation">{</span>@html article<span class="token punctuation">.</span>html<span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> |
Svelte có cú pháp khai báo script tương tự Vue, nếu bạn từng sử dụng Vue thì việc học Svelte càng đơn giản
Như giới thiệu thì Sapper là một Nextjs type, nên với các bạn đã tiếp xúc nhiều với các framework thì Sapper có vẻ như không có gì đặc biệt. Trong bài tiếp theo mình sẽ tìm hiểu kĩ hơn về xử lý render DOM của Svelte. Hi vọng là sẽ có điều gì đó thú vị.
Tài liệu tham khảo:
https://sapper.svelte.dev/docs