Tạo website tĩnh với Jigsaw
Bài đăng này đã không được cập nhật trong 5 năm
Lời mở đầu
Hôm nay mình xin chia sẻ về 1 công cụ giúp ta tạo ra các website tĩnh 1 cách linh hoạt
. Trong thời buổi công nghệ đang chuyển biến mạnh, rất nhiều các công cụ sinh ra để phục vụ mục đích cho dân lập trình . Đối với tạo website tĩnh rất nhiều framework hỗ trợ như là Nuxt, Hugo, Jigsaw. Phạm vi bài viết này mình xin nói về Jigsaw - Một công cụ mình thấy khá gọn và cú pháp dễ hiểu nhất là đối với ai đã từng làm việc qua Laravel . Start thôi :d
Cài đặt
Với Jigsaw chúng ta có thể cài đặt thông qua composer bằng lệnh sau
$ mkdir my-site && cd my-site
$ composer require tightenco/jigsaw
Xong, chúng ta chạy lệnh dưới đây để tiến hành tạo ra cấu trúc thư mục của Jigsaw
$ ./vendor/bin/jigsaw init
Cấu trúc thư mục sau khi đã được tạo ra, chúng ta sẽ làm việc chủ yếu ở thư mục source
Biên dịch và cấu hình
Tiến hành build ra trang web tĩnh ta có thể chạy lệnh sau từ thư mục gốc của dự án
$ ./vendor/bin/jigsaw build
Hoặc cho môi trường production
$ ./vendor/bin/jigsaw build production
Sau đó ta có thể chạy lệnh sau để tiến hành theo dõi sản phẩm của mình
$ ./vendor/bin/jigsaw serve
Trong trường hợp chúng ta sử dụng Laravel Mix để biên dịch
$ npm install && npm run watch
Mặc định tính năng Laravel Mix trong jigsaw sẽ mix các file js css từ thư mục source/_assets tới source/assets/build để sửa các đường dẫn này chúng ta sẽ tìm tới file webpack.mix.js
Jigsaw cũng hỗ trợ cho ta cấu hình các biến môi trường tại file config.php, ngoài ra có những biến ta cấu hình riêng cho production thì ta sẽ tạo ra 1 file config.production.php , trong này ta chỉ cần cấu hình các biến thay đổi về bản chất jigsaw sẽ tự gộp tất cả các biến môi trường ở 2 file và sẽ ghi đè các biến được khai báo trong config.production.php
// Example config.php
return [
'production' => false,
'baseUrl' => '',
'collections' => [],
'titleWeb' => 'Sun Asterisk VN'
];
// Example config.production.php
return [
'production' => true,
];
Chúng ta có thể gọi các biến này trong Blade Template Engine ( Sẽ được giới thiệu ngay dưới đây thôi
) theo cú pháp sau :
@section('body')
<h1>Post Example</h1>
<p>
{{ $page->titleWeb }}
</p>
@endsection
Tạo nội dung
Jigsaw hỗ trợ biên dịch từ file Markdown và Blade Template engine rất thuận tiện cho việc tạo nội dung , với những bạn nào đã sử dụng qua Laravel chắc chả còn xa lạ gì nữa nhỉ
Trước hết chúng ta sẽ có 1 file master.blade.php trong thư mục source/_layouts
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<link rel="stylesheet" href="{{ mix('css/main.css', 'assets/build') }}">
</head>
<body>
@yield('body')
</body>
</html>
Tiếp là 1 file nội dung sẽ kế thừa từ master.blade.php như khi chúng ta code View trong Laravel vậy
# File : post.blade.php
@extends('_layouts.master')
@section('body')
<h1>Post Example</h1>
<p>
{{ $page->titleWeb }}
</p>
@endsection
Note :
Biến $page trên mặc định từ Jigsaw, trong ví dụ trên ta thấy nó truy cập vào thuộc tính titleWeb từ file config.php Ngoài ra chúng ta có thể gọi 1 số phương thức sau từ $page
$page->getPath() : trả về đường dẫn trang hiện tại từ thư mục gốc
$page->getUrl() : trả về URL đầy đủ nếu baseUrl được cấu hình trong config.php
$page->getFilename() : trả về tên tệp của trang, không có phần mở rộng
$page->getExtension() : trả về phần mở rộng của trang hiện tại
Và 1 file Markdown content.md ( lưu ý là chúng ta thay đổi phần extends với section tương ứng với thư mục của dự án nhé )
---
extends: _layouts.master
section: body
---
### Sun Asterisk
https://sunasterisk.vn

Tiến hành biên dịch thôi
$ ./vendor/bin/jigsaw build
Ta sẽ thấy có 1 folder build_local xuất hiện và các file blade cũng như markdown đã được biên dịch thành các thư mục kèm file index.html chứa nội dung bên trong build_local
Đối với một người học về laravel như mình thì mình khá thích cách viết nội dung của Jigsaw như này :d Nhưng còn một thắc mắc nhỏ , trong master.blade.php có thể sử dụng yield để cho các view con có thể kế thừa nội dung từ master layouts. Vậy mình có thể sử dụng @include như trong Laravel để chèn Header hay Footer được không nhỉ. Chắc chắn rồi đều từ 1 Blade engine ra thì mình nghĩ là làm được thôi. Cùng thử nhé :d
Đầu tiên mình tạo thư mục _partials và có file header.blade.php ( lưu ý là tên thư mục các bạn để thế nào cũng được nhé , và cho chúng nằm trong /source )
# Ex : _partials/header.blade.php
<h1>Header Content</h1>
Tiếp đến ở master.blade.php mình sửa lại thành như sau
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<link rel="stylesheet" href="{{ mix('css/main.css', 'assets/build') }}">
</head>
<body>
@include('_partials.header')
// hoặc @include('_partials.header', ['page_title' => 'My Website'])
// Nếu mình muốn truyền các biến qua bên header, khi đó trang header mình sẽ gọi $nameVar tương ứng
@yield('body')
</body>
</html>
Save lại thôi nào , mình sử dụng npm run watch trong quá trình dev nên khi save nó sẽ tự build cho mình
Làm việc với collection
Làm gì đó thú vị hơn đi , thử lấy các post từ 1 API Json về xem thế nào nhỉ :-?
Mình vào sửa config.blade.php như sau
<?php
return [
'production' => false,
'baseUrl' => '',
'collections' => [
'reddit' => [
'extends' => '_layouts.reddit',
'items' => function () {
$posts = json_decode(file_get_contents('https://www.reddit.com/r/aww.json?raw_json=1'));
return collect($posts->data->children)->map(function ($post) {
return [
'id' => $post->data->id,
'title' => $post->data->title,
'thumbnail' => $post->data->thumbnail,
'content' => ""
];
});
},
],
],
];
Ở trên mình có 1 item reddit trong biến collections , ở đây mình khai báo extends để nó sẽ hiển thị nội dung theo 1 file template nào đó ( trong ví dụ này của mình là _layouts/reddit.blade.php ) và trong các items mình sẽ viết 1 function lấy về các bài viết từ 1 file json sau đó map chúng ra các trường dữ liệu mình cần :-? Và cuối cùng trong file template mình liệt kê danh sách các items như khi làm view trong laravel , dùng @foreach XD
@extends('_layouts.master')
@section('body')
<h1>Post Example</h1>
<p>
<ul>
@foreach ($reddit as $post)
<li><a href="{{ $post->getUrl() }}">{{ $post->title }}</a>
@endforeach
</ul>
</p>
@endsection
Và đây là kết quả
Jigsaw còn hỗ trợ rất nhiều các function khác như phân trang , lọc , sắp xếp bla bla
Bài viết của mình còn thiếu xót nhiều lắm mong các bạn đóng góp thêm để mình cải thiện cho các bài sau
. Hy vọng với những gì mình tìm hiểu và chia sẻ , các bạn sẽ có thêm những công cụ tuyệt vời hơn trong con đường làm web của mình !
Tài liệu tham khảo :
All rights reserved



