Yayına almak
Statik dışa aktarma
Siteyi collage export ile statik dosyalara render edin — neler yazılır, neler neden atlanır, dinamik yollar ve statik barındırma hizmetinde yayımlama.
Sayfaları gelen isteğe göre değişmeyen bir sitenin sunucuya hiç ihtiyacı yoktur.
collage export, dosya olabilecek her sayfayı dist/ içine render eder, statik
dosyalarınızı yanlarına kopyalar ve sitenin kendi 404.html'ini yazar. Dizini
herhangi bir statik barındırma hizmetine koyun.
Siteyi sunan programın ta kendisidir; aynı şablonlar, data handler'lar ve plugin'ler üzerinden render eder. İkinci bir build yoktur, sunucuyla uyumlu tutulması gereken bir şey de yoktur. Okuduğunuz sayfalar bu yolla üretildi.
collage export # -> dist/
collage export -clean # empty dist/ first
collage serve # look at dist/ the way a static host would serve it
Nasıl çalışır
collage export uygulamanızı yüklemez — yükleyemez de, çünkü uygulamanız sizin
kodunuzdur. Bunun yerine programınızı özel bir modda çalıştırır:
go run . -collage-build -out dist # plus -clean when you passed it
| Flag | Varsayılan | Anlamı |
|---|---|---|
-out dir |
dist |
Dosyaların yazılacağı yer. |
-clean |
kapalı | Önce dizinin mevcut içeriğini kaldırır. |
İskeleti oluşturulan main.go bu sözleşmeye uyar: -collage-build verildiğinde
uygulamayı her zamanki gibi kurar ve onu sunmak yerine collage'ın builder'ına
verir, ardından ne olduğunu yazdırır. Bu fonksiyonun collage-docs sürümü şudur:
func staticBuild(app *collage.App, outDir string, clean bool) error {
loaded, err := site.Load(content.FS)
if err != nil {
return err
}
builder, err := collage.NewBuilder(app, collage.BuildOptions{
OutDir: outDir,
Clean: clean,
PathProvider: docPaths{loaded},
})
if err != nil {
return err
}
report, buildErr := builder.Build(context.Background())
collage.PrintBuildReport(os.Stdout, report, buildErr)
return buildErr
}
Build, bir hata döndürdüğünde bile bir rapor döndürür: hata veren bir sayfa
diğerlerini durdurmaz ve her hata report.Errors içindedir. Dönen hata bunların
hepsinin birleşimidir ve main onunla sıfırdan farklı bir kodla çıkar; böylece bir
sayfa yazılamadığında CI işi başarısız olur. Atlanan sayfalar ve uyarılar build'i
başarısız kılmaz.
main.go'yu yeniden yazarsanız -collage-build, -out ve -clean flag'lerini
koruyun; yoksa collage export işe yarar bir şey yapmaz olur.
Neler yazılır
| Ne | Nereye |
|---|---|
Static() ya da Incremental(ttl) bir sayfa |
dist/<path>/index.html; / için dist/index.html |
| Aynı sayfa, varsayılan olmayan bir locale'de | Locale'in önekinin altına: dist/tr/<path>/index.html |
Static() ya da Incremental(ttl) bir document |
Birebir kendi yoluna: /sitemap.xml için dist/sitemap.xml |
| Aynı document, varsayılan olmayan bir locale'de | Locale'in önekinin altına: dist/tr/sitemap.xml |
AtRoot ile kurulan bir document |
Her yapılandırmada öneksiz yoluna: dist/robots.txt |
PrefixDefault ile varsayılan locale'deki bir sayfa ya da document |
Onların da önekinin altına, dist/en/<path>/index.html ve dist/en/sitemap.xml; dist/index.html ise okuyucuyu /en/'e gönderir |
| Bulunamadı sayfası | dist/404.html ve diğer her locale için dist/<locale>/404.html |
| Mount edilmiş her statik dosya sistemi | Kendi önekinin altına: /static/app.css için dist/static/app.css |
Bir sayfa, içinde index.html olan bir dizin olur; her statik barındırma hizmeti
/about istendiğinde bunu arar. Bir document ise tam olarak kendi
yoluna yazılır, çünkü /robots.txt isteyen bir tarayıcı botu bir dosya almalıdır.
Bulunamadı sayfası app.RegisterNotFoundPage'den gelir ve render stratejisine
bakılmaz — neredeyse her zaman Dynamic()'tir, çünkü önbelleğe almaya asla değmez;
yine de dışa aktarmada yeri vardır. Barındırma hizmetleri iç içe bir tr/404.html
arayıp aramamakta farklılaşır, bu yüzden ikisi de yazılır. Bulunamadı sayfası olmayan
bir site dosya almaz ve bilinmeyen bir URL, barındırma hizmeti ne gösterirse onu
gösterir.
Mount edilmiş asset'ler hem özgün adlarıyla hem de {{asset}}'in bağlandığı
içerik adresli adlarla (app.3a3663df.css) kopyalanır; böylece iki tür bağlantı da
çalışır. Production'da bir CDN'den sunulan ya da çoğaltılamayacak kadar büyük bir
mount bunun dışında kalmayı seçebilir:
app.Mount("/media/", mediaFS, collage.WithoutBuildCopy())
Bkz. Statik asset'ler.
Neler atlanır
Bazı sayfalar dosya olamaz. Build onları dışarıda bırakır ve her birini raporda, nedeniyle birlikte adlandırır:
Dynamic()sayfalar ve document'lar. İstek başına render edilmek için vardırlar.- Form içeren sayfalar. Render'ı
{{csrfToken}}içeren bir sayfa atlanır: bir formun gönderileceği bir sunucuya ihtiyacı vardır ve sahtecilik token'ı tek bir okuyucuya aittir. Sayfa bilerekStatic()olabilir — önbelleğe alınmış ve gönderildiği action tarafından geçersiz kılınan — ve dışa aktarılmak yerine sunulur. İskeletteki/featuressayfası böyledir. - Path provider'ı olmayan bir
{param}pattern'i./blog/{slug}, bir şey hangi slug'ların var olduğunu söyleyene kadar yazılamaz. Aşağıya bakın. - Tek bir dosyaya düşen iki document. Bir yolu iki kez döndüren bir
DocumentPathProvider, iki görevi tek bir dosyaya çözer; ilki yazılır, gerisicollage.ErrDuplicateOutputPathile atlanır. İki locale'deki tek bir pattern bu durum değildir — her locale kendi önekinin altına yazılır. Bkz. Document'lar.
Yol olmadan kaydedilmiş hata sayfaları hiç listelenmez: URL değildirler.
Sayfa olmadıkları için dışa aktarılmayan ve raporlanmayanlar:
action'lar, app.Handle ile mount edilen handler'lar
ve middleware. Dışa aktarma istek olmadan render eder; bu yüzden hiçbir middleware
çalışmaz ve collage.Vary hiç çağrılmaz — her sayfa, hiçbir tercihi olmayan bir
isteğin alacağı sürümüyle yazılır.
Neler için uyarılır
WithCacheParams ile hangi query parametrelerini okuduğunu bildiren bir sayfa, her
biri için farklı render edilir. Bir dosyanın query string'i yoktur: statik
barındırma hizmeti /blog?page=2'ye /blog dosyasıyla yanıt verir. Sayfa query
olmadan yazılır ve sayfalanmış bir arşivin çalışıyormuş gibi görünmesine izin
vermek yerine rapor bunu söyler. WithCacheParams içeren bir document — sayfalanmış
bir feed — için de aynı şekilde uyarılır (v0.10.0'dan itibaren; öncesinde yalnızca
sayfalar için uyarılıyordu).
Sayfalamanın dışa aktarmada çalışması gerekiyorsa sayfa numarasını yola koyun —
/blog/page/{n} — ve sayfaları bir path provider ile listeleyin.
Neler başarısız olur
Bunlar hatadır: sayfa yazılmaz, build bunu raporlar ve sıfırdan farklı bir kodla çıkar.
- Kusurlu bir render. Bir fragment'in hata verdiği bir sayfa, fragment'i
adlandıran
collage.ErrDegradedRenderile reddedilir. Hata veren fragment'i olan sunulmuş bir sayfa gösterilir ama asla önbelleğe alınmaz; bir dosyanın ise toparlanabileceği bir TTL'i yoktur, bu yüzden hatayı bir sonraki dışa aktarmaya kadar taşırdı. Eksik bir kenar çubuğu olan bir sayfa hiç sayfa olmamasından iyiyseBuildOptions.AllowDegraded'ı ayarlayın. - Boş bir render,
collage.ErrEmptyRender, ve boş bir document,collage.ErrEmptyDocumentBody. Sıfır baytlık birindex.htmlasla yazılmaz. - Bir sayfadaki panic,
collage.ErrBuildPanic. Yakalanır ve o sayfanın hanesine kaydedilir; build'in geri kalanı devam eder. - Form içeren bir bulunamadı sayfası,
collage.ErrUnresolvedToken, çünkü statik barındırma hizmetinin o sayfaya bir dosya olarak ihtiyacı vardır. - Tek bir çıktı yoluna düşen iki sayfa,
collage.ErrOutputPathCollision— yalnızca sondaki eğik çizgiyle ayrılan iki pattern ya da bir yolu iki kez döndüren bir path provider. Bu bulunduğunda hiçbir sayfa render edilmez; document'lar,404.htmlsayfaları ve mount edilmiş asset'ler yine yazılır ve build yine başarısız olur.
Dinamik yollar: PathProvider
/blog/{slug}'daki bir sayfa, birçok URL'si olan tek bir sayfadır. Builder bunları
bir collage.PathProvider'a sorar:
type PathProvider interface {
Paths(ctx context.Context, page *collage.Page, locale string) ([]collage.PathInstance, error)
}
Her dinamik sayfa ve locale için bir kez çağrılır; somut yolları ve her birinin
yakaladığı parametreleri döndürür. Bu belgeler, /docs/{slug} üzerindeki tek bir
sayfadır, doc; provider belgelerin her sayfasını listeler:
// docPaths tells the static build which /docs/{slug} pages exist: every page of
// the documentation, and nothing else.
type docPaths struct{ site *site.Site }
func (d docPaths) Paths(_ context.Context, page *collage.Page, _ string) ([]collage.PathInstance, error) {
if page.Name != "doc" {
return nil, nil
}
var paths []collage.PathInstance
for _, p := range d.site.Pages() {
paths = append(paths, collage.PathInstance{Path: p.URL(), Params: map[string]string{"slug": p.Slug}})
}
return paths, nil
}
- Sayfayı kontrol edin. Tek bir provider her dinamik sayfaya yanıt verir.
Tanımadığınız bir sayfa için
nildöndürmek onun için hiçbir şey yazmaz; bu bir hata değildir. Params, data handler'ların gördüğüdür. Router'ınPath'ten yakaladığının üzerine bindirilir; böylecerc.Param("slug")canlı bir isteğin alacağı değere sahip olur.Pathlocale öneki olmadan verilir. Pattern'in yolunu,/blog/hello'yu döndürün; builder varsayılan olmayan bir locale'i kendi dizininin altına yazar.- Bir hata döndürmek onu o sayfa ve locale'in hanesine kaydeder ve devam eder.
{param} içeren document'ların kendi interface'i vardır,
BuildOptions.DocumentPathProvider; Document'lar sayfasında
anlatılır.
Bir provider'ın döndürdüğü her yol, kendi dosyası yazılmadan önce kontrol edilir:
çıktı dizininin dışına çözülecek bir yol — /../../etc —
collage.ErrPathEscapesOutDir ile reddedilir; dizinin dışına çıkan bir symlink
üzerinden yazma da öyle. Ret yalnızca o yolu başarısız kılar, etrafındaki build'i
değil: diğer sayfalar yine render edilip yazılır ve hata raporda yer alır.
Build seçenekleri
| Alan | Anlamı |
|---|---|
OutDir |
Nereye yazılacağı. Zorunlu. |
Clean |
Önce OutDir'in içeriğini (dizinin kendisini değil) kaldırır. |
Locales |
Yalnızca bu locale'leri derler. Boşsa bir sayfanın bildirdiği her locale derlenir. |
Concurrency |
Aynı anda kaç sayfanın render edilip yazılacağı. 0 ya da 1 birer birer demektir. Rapor her iki durumda da aynı sıradadır. |
PathProvider |
{param} içeren sayfalar için somut yollar. |
DocumentPathProvider |
{param} içeren document'lar için somut yollar. |
AllowDegraded |
Render'ında hata veren bir fragment olan sayfaları yazar. |
Builder, dosya sisteminin köküne çözülen bir OutDir'i reddeder ve bir deponun
kökü olan bir OutDir'i Clean etmeyi reddeder (collage.ErrDangerousOutDir) —
aksi hâlde -clean ile -out . projenizi silerdi.
Dışa aktarmada plugin'ler
Dışa aktarma, sunucunun render ettiği durumda render eder. Önce her plugin'in Init'i
çalışır, böylece plugin aynı yapılandırmayı okur; OnBeforeRender, OnAfterRender
ve OnDocumentRendered her sayfa ve document için tetiklenir, dolayısıyla bir
minifier ya da structured data plugin'i sunulan bir sayfaya ne yapıyorsa dosyaya da
onu yapar. OnPageResolved tetiklenmez, çünkü dışa aktarma bir istek değildir. Bkz.
Plugin kullanmak.
Raporu okumak
collage.PrintBuildReport build'in ne yaptığını yazdırır. collage new'un iskeletini
oluşturduğu proje için şöyle görünür:
✓ 8 files written
dist/404.html
dist/index.html
dist/static/app.3a3663df973f06fb.js
dist/static/app.7050c2518057f5c5.css
dist/static/app.css
dist/static/app.js
dist/static/favicon.936907e03c8c09ad.svg
dist/static/favicon.svg
▲ 3 skipped
hello page uses the dynamic render strategy, which cannot be built statically
features (en) page carries {{csrfToken}}; a form needs a server to submit to, so it is served rather than exported
health document uses the dynamic render strategy, which cannot be built statically
8 written · 3 skipped · 0 failed · 2.5ms
Yazılan dosyalar ondan sonra özetlenir, çünkü üç yüz dosya yazan bir build atladığı
tek sayfayı gömmemelidir. Atlananlar, uyarılar ve hatalar asla kısaltılmaz. Son
satırda bütün sayılar vardır ve aralarındaki en kötüsüne göre renklendirilir.
v0.10.0'dan itibaren atlananlar route olarak, sayfalar ve document'lar birlikte
sayılır — 3 pages skipped değil, 3 skipped.
Rapora göre kodda işlem yapmak için report.Skipped, report.Warnings ve
report.Errors'u kendiniz okuyun. Her atlama, route'un adını (Page), Locale'ini,
insanlar için bir Reason'ı ve v0.10.0'dan itibaren errors.Is ile eşleştirilecek
bir Err'i içeren bir collage.SkipRecord'dur — bkz.
Hatalar.
Test bunu bir teste dönüştürür.
Renk ve ✓ ▲ ✗ işaretleri yalnızca bir terminalde görünür, NO_COLOR ayarlıyken de
görünmez. Bir CI logunda işaretler düz ASCII'dir (+ ! x).
Göz atmak: collage serve
dist/index.html'i bir tarayıcıda açmak işe yaramaz: bir file:// sayfasının kökü
yoktur, bu yüzden her mutlak bağlantı ve stil dosyası bozuk olur. collage serve
dışa aktarılan siteyi bir statik barındırma hizmetinin sunduğu gibi sunar:
collage serve # http://localhost:4000
collage serve -dir public -port 8000
/aboutisteğineabout/index.htmlile yanıt verilir.index.htmliçermeyen bir dizin 404'tür — dizin listelemesi yoktur.- Bilinmeyen bir yol, 404 durumuyla
404.html'i alır. - Hiçbir şey önbelleğe alınmaz; yeniden dışa aktarıp sayfayı yenilemek yeni çıktıyı gösterir.
Flag'leri -dir (varsayılan dist), -host (varsayılan localhost) ve -port
(varsayılan 4000 — 3000 değil, böylece karşılaştırırken collage dev'in yanında
çalışabilir). Dosya sunar; projenizi çalıştırmaz.
Barındırma
Çıktı, mutlak bağlantılara sahip düz dosyalardır; dolayısıyla herhangi bir statik barındırma hizmeti onu sunar. Hangisinde olursa olsun kontrol edilecek üç şey var:
- Site, alan adının kökünde olmalıdır. Bağlantılar ve asset URL'leri
/ile başlar ve collage'ın bir base-path ayarı yoktur; dolayısıyla bir alt yol altında yayımlanan bir site —user.github.io/project/adresindeki bir GitHub proje sayfası gibi — bozuk bağlantılara sahip olur. Özel bir alan adı ya da siteye kendi alan adını veren bir barındırma hizmeti kullanın. 404.htmlköktedir. Çoğu barındırma hizmeti onu hiçbir yapılandırma gerekmeden bu adla bulur.TrailingSlashaçıktır. Bir sayfa<path>/index.htmlolarak yazılır; barındırma hizmeti onu/about/adresinde sunar ve/about'u oraya yönlendirir. Ayar açıkken collage'ın kurduğu her bağlantı, oraya giden bir yönlendirme değil, doğrudan hizmetin yanıt verdiği adres olur.
GitHub Pages
Bu site, testleri çalıştıran, dışa aktaran ve dist/'i yükleyen bir workflow ile
yayımlanır:
name: pages
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.26'
- run: go test ./...
- run: go run . -collage-build -out dist -clean
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
Dışa aktarma adımı programı collage export üzerinden değil doğrudan çalıştırır;
böylece runner'da collage CLI'ının kurulu olması gerekmez. Deponun Pages kaynağını
GitHub Actions olarak ayarlayın ve user.github.io deponuz değilse ona özel bir alan
adı verin.
Cloudflare Pages
CI'da aynı şekilde dışa aktarın ve dizini Wrangler ile yükleyin:
go run . -collage-build -out dist -clean
npx wrangler pages deploy dist --project-name mysite
Cloudflare Pages, kökte bir 404.html varsa bilinmeyen yollar için onu sunar;
sitenin bir bulunamadı sayfası olduğunda dışa aktarma bu dosyayı her zaman yazar.
Diğerleri
Netlify, CloudFront arkasında S3, bir nginx dizini — her birinin ihtiyacı yalnızca
dist/'in içeriği ve, zaten yapmıyorsa, hata sayfası olarak yapılandırılmış
404.html'dir. Site formlara, önizlemelere ya da istek başına sayfalara ihtiyaç
duyduğunda ise bir sunucuya ihtiyaç duyar: bkz. Yayına alma.