Next.js: Permintaan fitur: Dukungan Basepath

Dibuat pada 21 Agu 2018  ·  73Komentar  ·  Sumber: vercel/next.js

Permintaan fitur

Apakah permintaan fitur Anda terkait dengan masalah? Tolong jelaskan.

Multi zona adalah fitur hebat yang memungkinkan untuk menjalankan beberapa aplikasi next.js di domain yang sama, tetapi tidak memungkinkan untuk menentukan jalur dasar yang akan diterima oleh semua bagian next.js. Karena kami tidak dapat menggunakan aplikasi namespace saat ini, tidak mungkin memiliki nama yang sama untuk halaman di berbagai aplikasi.

Jelaskan solusi yang Anda inginkan

Saya ingin dapat mengkonfigurasi basepath di file next.config.js. Berkat konfigurasi ini, semua bagian next.js (Router, Link, Static assets, dll.) Akan mengetahui jalur dasar dan secara otomatis akan menghasilkan dan mencocokkan ke jalur yang benar.

Jelaskan alternatif yang telah Anda pertimbangkan

Salah satu alternatifnya adalah mengumpulkan semua halaman yang diinginkan ke dalam folder yang cocok dengan jalur dasar. Ini hanya memecahkan satu masalah kecil dengan perutean dan cukup jelek karena sebagian besar basepath saya bukan jalur satu tingkat.
Alternatif kedua adalah mengonfigurasi proxy dengan cara di mana jalur dasar dihapus secara otomatis sebelum permintaan masuk ke aplikasi next.js dan juga menerapkan komponen Tautan khusus yang secara otomatis menambahkan jalur dasar ke semua tautan. Saya hanya tidak ingin mempertahankan garpu kustom next.js. Tidak masuk akal menurut saya.

Konteks tambahan

Solusi assetPrefix memungkinkan kita menentukan awalan yang berbeda untuk setiap aplikasi. Tapi seadil yang saya tahu itu hanya berfungsi dengan host yang berbeda.

contoh dengan zona

module.exports = {
  assetPrefix: NOW_URL ? `https://${alias}` : 'http://localhost:4000'
}

Jika saya menambahkan basepath padanya semuanya gagal

module.exports = {
  assetPrefix: NOW_URL ? `https://${alias}/account` : 'http://localhost:4000/account'
}

screen shot 2018-08-21 at 10 47 08

Menurut saya kita harus membaginya menjadi 2 variabel:

module.exports = {
  assetPrefix: NOW_URL ? `https://${alias}` : 'http://localhost:4000',
  basepath: '/account'
}

Masalah terkait

story needs investigation

Komentar yang paling membantu

Setiap pembaruan tentang ini ... tahun lalu sekitar waktu ini saya mengalami masalah ini. Sekarang setahun kemudian, saya mengerjakan aplikasi baru dan harus melakukan solusi yang sama yang saya lakukan tahun lalu ... agak mengkhawatirkan untuk reaksi 'siap produksi'. Basepaths harus menjadi fitur vanilla.

Saya tidak yakin apa yang Anda harapkan dengan memposting ini.

Next.js sedang dikerjakan penuh waktu oleh tim saya (5 orang), dan kami mengerjakan banyak fitur pada waktu yang sama. Pada tahun lalu kami telah mengerjakan ini:

Secara efektif membuat aplikasi Next.js (baru dan yang sudah ada) secara signifikan lebih kecil, lebih cepat, dan lebih skalabel.

Jika Anda ingin menyuarakan "upvote" Anda untuk suatu fitur, Anda bisa. gunakan fitur 👍 di utas awal.

Saya sangat setuju basePath harus menjadi fitur bawaan. Itu sudah ada di peta jalan dan saya bahkan menulis PR awal, yang bisa Anda lihat dengan membaca kembali di utas.

Inilah PR: https://github.com/zeit/next.js/pull/9872

Jangan ragu untuk menghubungi [email protected] jika Anda ingin berkontribusi secara finansial untuk mewujudkan fitur ini.

Semua 73 komentar

cc

cc @alexindigo @dullReferenceExeption

Akan sangat senang mendapat tanggapan Anda 👍

Setelah bermain dengan kode, saya menyadari bahwa akan jauh lebih mudah untuk membagi assetPrefix menjadi beberapa bagian:

module.exports = {
  host: NOW_URL ? `https://${alias}` : 'http://localhost:3000',
  basePath: '/account',
}

Kita masih dapat menyimpan variabel assetPrefix secara internal, tetapi pengguna harus mendefinisikan lebih tepat apa yang dia butuhkan.

Untuk bagian aset sangat baik untuk menyediakan dua variabel ini bersama-sama.
Untuk routing dll kita membutuhkannya secara terpisah.
Atau mungkin kita bahkan dapat menyediakannya bersama dalam file konfigurasi dan kemudian membaginya di basis kode next.js. Dalam hal ini assetPrefix bukanlah nama yang tepat, saya khawatir.

Sebagai efek samping, ini juga menyebabkan lebih sedikit perubahan kode.
Cukup jelas jika Anda membandingkan kedua PR tersebut:
https://github.com/panter/next.js/pull/2 (split)
https://github.com/panter/next.js/pull/1 (lewati keduanya)

Menurut pendapat saya, mereka harus terpisah, alasannya adalah tidak rusak dan lebih fleksibel untuk menyimpan assetPrefix dan memiliki basePath terpisah.

Apakah assetPrefix nama yang benar? Kedua variabel tersebut sebenarnya adalah awalan bukan?

assetPrefix adalah untuk aset misalnya: bundel halaman. basePath akan digunakan untuk router.

Cara kerjanya adalah:

  • jika assetPrefix didefinisikan gunakan assetPrefix untuk memuat bundel, jangan sentuh router (perilaku saat ini)
  • jika assetPrefix dan basePath disediakan gunakan assetPrefix untuk memuat bundel, tambahkan basePath ke router
  • jika assetPrefix tidak ditentukan dan basePath adalah, gunakan basePath untuk memuat bundel, dan tambahkan basePath ke router
  • jika tidak ada assetPrefix atau basePath yang ditentukan, kami tidak melakukan hal yang berbeda (perilaku saat ini ketika assetPrefix tidak tersedia)

cc @alexindigo @DullReferenceExeption @ 3rd-Eden

Bisakah Anda memberikan umpan balik untuk proposal di atas: https://github.com/zeit/next.js/issues/4998#issuecomment -414978297

@tomaswitek Tidak yakin apa yang sebenarnya tidak berhasil untuk Anda dengan assetPrefix ini, ini adalah awalan aset yang kami gunakan dalam produksi: "assetPrefix":"https://static.trulia-cdn.com/javascript" dan berfungsi seperti yang diharapkan.

Dan secara umum, kami menggunakan beberapa zona (kami menyebutnya pulau) pada domain yang sama dan "basePathing" setiap pulau tidak pernah terlintas dalam pikiran kami, karena hal itu akan mempersulit interoperabilitas antar pulau. Izinkan saya menjelaskan lebih lanjut:

Jadi kami memiliki dua pulau A dan B , dan gagasan utamanya adalah transparansi bagi pengguna yang menavigasi pulau ke pulau sebagai bagian dari pengalaman satu situs web mereka. Jadi harus ada hubungan antar pulau. Lalu ada masalah penerapan vs. masalah aplikasi.

  1. Masalah penerapan vs. masalah aplikasi - aplikasi tidak tahu di mana ia dapat diterapkan, ia hanya tahu cara menangani permintaan http yang masuk - ia telah menetapkan rute yang dapat ditanggapi.
    Ketika diterapkan di suatu tempat - bisa jadi domain yang berbeda, port yang berbeda, dan ya secara teoritis bisa jadi basePath yang berbeda, yang akan dibuat transparan untuk aplikasi melalui proxy atau cara lain.

  2. Hubungan silang antar pulau - untuk menjaga semangat pulau sebagai entitas terpisah yang dapat diterapkan, tidak boleh ada kebocoran pengetahuan implementasi internal antara pulau yang berbeda.
    Jadi cara terbaik bagi pulau untuk mereferensikan halaman satu sama lain, adalah bagi mereka untuk mengekspor rute yang tersedia untuk dikonsumsi pulau lain (_dan di dunia selanjutnya sepertinya komponen kustom <IslandALink> akan lebih disukai cara_).
    Sejauh ini semuanya mudah - semua pulau berasumsi untuk berbagi domain yang sama dan memiliki kumpulan jalur absolut ( /path1 , path2 , dll). Dengan cara itu pulau kedua mengimpor daftar jalur itu dan mengandalkannya agar stabil. Pada saat yang sama, sangat minim persyaratan untuk setiap pulau agar jalur mereka tetap kompatibel (yang merupakan hal yang baik di web) :)

Saat kami menambahkan basePath khusus penerapan, kami secara otomatis meningkatkan kompleksitas seluruh sistem - haruskah setiap pulau mengetahui (dan mungkin mendikte) penerapan basePath itu sendiri? Lalu apa bedanya dengan cara kerjanya saat ini? Atau haruskah pulau A menjadi agnostik dari jalur penyebarannya? Lalu bagaimana pulau B akan menemukan pulau A yang dikerahkan, karena pulau itu hanya mengetahui apa yang diketahui pulau A tentang dirinya? Atau Anda harus memasok basePath untuk semua pulau yang dikerahkan ke semua pulau lainnya? Dan dengan cara modern menghentikan penyebaran, itu berarti mengerahkan kembali semua pulau saat Anda perlu menambahkan yang baru.

Atau bagaimana Anda membayangkan bagian cerita itu?

Terima kasih.

^ itu ditulis sebelum kopi pagi, jadi tolong beri tahu saya jika Anda membutuhkan penjelasan yang lebih koheren untuk bagian mana pun. :)

Pertama-tama terima kasih teman-teman yang telah meluangkan waktu untuk meninjau masalah saya.

@timneutkens Ya assetPrefix memiliki prioritas di atas basePath , itulah yang telah kita diskusikan di awal. Setelah saya melihat berapa banyak file yang harus saya ubah, saya pikir cara kedua akan lebih bersih. Tapi saya akan memutar kembali ke solusi pertama. Mari kita pisahkan sepenuhnya, tidak masalah sama sekali. Saya hanya berpikir keras.

@alexindigo Thx untuk jawaban rinci Anda. Biarkan saya mencoba menjawab pertanyaan Anda 😏

Tidak yakin apa yang sebenarnya tidak berhasil untuk Anda dengan asetPrefix saat ini

Saya punya dua masalah di sini:

  1. Saya tidak dapat bekerja dengan beberapa domain atau subdomain dalam proyek ini. (Pembatasan domain dan tidak ada sertifikat SSL wildcard)
  2. Implementasi assetPrefix pada satu domain membutuhkan lebih banyak penyesuaian dalam perutean proxy, file statis, dll. Kita dapat mengurangi penyesuaian ini dengan memperkenalkan basePath . Itu tidak akan merusak apa pun dan tidak akan meningkatkan kerumitan karena Anda tidak perlu menyediakan basePath seperti yang telah disebutkan @timneutkens .

aplikasi tidak tahu di mana itu bisa diterapkan

Tentu saja kami memiliki tujuan yang sama di sini! Kami mendefinisikan assetPrefixes secara dinamis dalam solusi saat ini yang kami miliki. Ini disediakan melalui header permintaan oleh proxy.

Lalu apa bedanya dengan cara kerjanya saat ini?

Router akan mengetahui contextPath dan akan mengurangi jumlah kode kustom.

haruskah setiap pulau mengetahui (dan mungkin mendikte) penyebaran basePathnya sendiri? Atau haruskah pulau A menjadi agnostik dari jalur penyebarannya?

Tidak harus seperti itu. Pengembang harus memiliki kebebasan di sini. Harus memungkinkan untuk menyediakan basePath secara dinamis dengan cara yang sama seperti assetPrefix.

Lalu bagaimana pulau B akan menemukan pulau A yang dikerahkan, karena pulau itu hanya mengetahui apa yang diketahui pulau A tentang dirinya? Atau Anda harus memasok basePath untuk semua pulau yang dikerahkan ke semua pulau lainnya? Dan dengan cara modern menghentikan penyebaran, itu berarti mengerahkan kembali semua pulau saat Anda perlu menambahkan yang baru.

Mungkin Anda juga bisa menambahkan basePath ke ekspor rute. Saya tidak tahu. Saya tidak mengatakan bahwa variabel basePath penting untuk setiap kasus penggunaan. Sepertinya ini bukan solusi terbaik untuk Anda. Tapi itu tidak masalah. Masalahnya adalah Anda masih dapat menggunakan hanya assetPrefix dan tidak ada yang akan berubah untuk pulau Anda. Sepertinya Anda memiliki perutean sendiri. Hubungan silang antar zona bahkan tidak penting untuk proyek kami, zona kami benar-benar independen dan terisolasi satu sama lain.

Dan dengan cara modern menghentikan penyebaran, itu berarti mengerahkan kembali semua pulau saat Anda perlu menambahkan yang baru.

Saya tidak melihat alasan mengapa. Saya bahkan dapat membayangkan bahwa beberapa zona memiliki basePaths dan beberapa tidak. Dan mungkin beberapa aplikasi akan menggunakan konfigurasi basePath bahkan tanpa pengaturan multi zona.

@alexindigo dapatkah Anda memberi kami dua url pulau nyata, yang ditampilkan oleh next.js sehingga saya dapat melihatnya beraksi? Saya mencoba menemukannya, tetapi tidak dapat menemukan halaman di domain Anda dengan _next request 😄
Apakah semua pulau Anda memiliki konfigurasi yang sama?
"assetPrefix":"https://static.trulia-cdn.com/javascript"

@tomasitek

Saya tidak dapat bekerja dengan beberapa domain atau subdomain dalam proyek ini. (Pembatasan domain dan tidak ada sertifikat SSL wildcard)

Oh, jadi Anda tidak menggunakan CDN dalam arti klasik, tetapi mengandalkan aset yang diambil dari setiap aplikasi secara langsung? Saya melihat.

Implementasi assetPrefix saat ini pada satu domain membutuhkan lebih banyak penyesuaian dalam perutean proxy, file statis, dll. Kami dapat mengurangi penyesuaian ini dengan memperkenalkan basePath. Itu tidak akan merusak apa pun dan tidak akan meningkatkan kompleksitas karena Anda tidak perlu menyediakan basePath seperti yang telah disebutkan @timneutkens .

Btw, itu bukan "tidak, jangan tambahkan fitur itu" :) Itu lebih seperti - "Mungkin kita bisa memikirkan pendekatan ini secara lebih holistik" :)

Tidak harus seperti itu. Pengembang harus memiliki kebebasan di sini. Harus memungkinkan untuk menyediakan basePath secara dinamis dengan cara yang sama seperti assetPrefix.

Iya. Ini hanya berfungsi jika tidak ada penghubung antar pulau. Dan sepertinya ini adalah kasus penggunaan Anda. Pada saat yang sama, saya kesulitan memahami apa yang membuat mereka menjadi pulau alih-alih hanya menjadi sekumpulan aplikasi mandiri, jika mereka 100% independen? :)

Mungkin Anda juga bisa menambahkan basePath ke ekspor rute.

Saya tidak melihat bagaimana hal itu dapat dilakukan (dengan mudah), karena ekspor rute terjadi pada waktu pembuatan, dan basePath ditentukan pada waktu penerapan, dan mungkin ada lebih dari satu penerapan artefak kode yang sama (tahap, preprod, prod, menguji env, dll).


Apakah semua pulau Anda memiliki konfigurasi yang sama?
"assetPrefix": " https://static.trulia-cdn.com/javascript "

Ya, semua pulau berbagi asetnya, karena selanjutnya melakukan hashing konten, itu bukan hanya bukan masalah, tetapi sebenarnya sangat menguntungkan. (Kami mengekstrak aset yang dibangun dari setiap artefak dan memublikasikannya di CDN pada waktu penerapan).

Dan dengan begitu kami hanya memiliki permintaan "html biasa" ke server aplikasi kami, inilah mengapa saya tidak akan melihat jalur "_next" di trulia.com

Adapun contoh pulau:

Pulau baru kami yang baru - Laman lingkungan - https://www.trulia.com/n/ca/san-francisco/pacific-heights/81571 (dan Anda dapat menemukannya lebih banyak di sini: http: //www.trulia. com / lingkungan)
Pulau ini bertanggung jawab atas semua jalur /n/* .

Dan pulau lain adalah halaman login kami - https://login.trulia.com/login - terlihat seperti domain yang berbeda, tetapi sebenarnya tidak, terlihat seperti itu karena berbagai alasan, tetapi secara teknis ini adalah penerapan yang sama. :)
Dan pulau ini menangani url seperti /login , /signup .

Beritahu saya jika Anda memiliki pertanyaan lebih lanjut.

@alexindigo terima kasih banyak atas contoh Anda.
Saya punya beberapa pertanyaan setelah menguraikan contoh 😄

Anda masih melakukan rendering server untuk setiap pulau, tetapi Anda mencoba mengekstrak aset sebanyak mungkin ke dalam CDN umum, bukan?

Bisakah Anda menjelaskan sedikit lebih banyak tentang apa yang sebenarnya terjadi ketika https://www.trulia.com/n/ca/san-francisco/pacific-heights/81571 dipanggil? Apakah proxy Anda tahu bahwa /n singkatan dari ikhtisar lingkungan dan meneruskannya ke pulau yang benar? Apakah hal itu mempengaruhi permintaan sebelum tiba di pulau?

Apakah Anda menggunakan perutean bawaan dari dalam pulau berikutnya atau apakah Anda memiliki solusi khusus?
Saya ingin memeriksa rute di dalam pulau Anda. Sayangnya Neighborhood overview memiliki lebih banyak atau lebih sedikit navigasi modal saja tanpa mengubah url. Di Login, sepertinya ada solusi yang sepenuhnya disesuaikan.

Saya harap saya akan menjawab semua pertanyaan Anda di komentar ini 😏

Btw, itu bukan "tidak, jangan tambahkan fitur itu" :) Itu lebih seperti - "Mungkin kita bisa memikirkan pendekatan ini secara lebih holistik" :)

Tentu, alangkah baiknya menemukan solusi di mana saya tidak perlu menyentuh next.js 😏

Iya. Ini hanya berfungsi jika tidak ada penghubung antar pulau. Dan sepertinya ini adalah kasus penggunaan Anda. Pada saat yang sama, saya kesulitan memahami apa yang membuat mereka menjadi pulau alih-alih hanya menjadi sekumpulan aplikasi mandiri, jika mereka 100% independen? :)

Saya tidak pernah menulis atau mengatakan bahwa saya mencari solusi "pulau". Saya baru saja mengobrol dengan @timneutkens di mana saya menjelaskan masalah saya dan jawaban Tim pada dasarnya next.js tidak mendukung basepaths. Dan setelah googling sedikit saya menyadari bahwa saya bukan satu-satunya yang mencarinya. Jadi saya pikir saya bisa berkontribusi sedikit. Setelah itu Tim menghubungi Anda untuk memberi saya umpan balik dan saya sangat berterima kasih atas umpan balik Anda.

Saya tidak melihat bagaimana hal itu dapat dilakukan (dengan mudah), karena ekspor rute terjadi pada waktu pembuatan, dan basePath ditentukan pada waktu penerapan, dan mungkin ada lebih dari satu penerapan artefak kode yang sama (tahap, preprod, prod, menguji env, dll).

Jika Anda ingin mengekspor rute pada waktu pembuatan dan membuatnya tersedia untuk pulau lain, maka satu-satunya cara mudah adalah dengan melakukan hardcode basePath di konfigurasi. Saya mengerti maksud Anda. Di sisi lain, apakah itu benar-benar masalah? Anda masih dapat menerapkan aplikasi ke domain dan port yang berbeda dan Anda dapat menggunakan basePath yang sama untuk setiap env.

Selamat pagi @omasekih :)

Pengalaman saya dengan fungsionalitas "basePath", yang sangat menipu dalam kerumitannya, dan biasanya lebih baik menerapkan hal semacam itu tanpa terburu-buru dengan satu masalah khusus,
tapi melihatnya dari berbagai sudut. Mirip dengan cara Anda mendekati penggabungan mendalam - buat garis besar beberapa kasus penggunaan dan lihat bagaimana (dan jika) semuanya berada di bawah satu payung. Karena memiliki fitur yang tidak kompatibel antara versi (bahkan utama) kerangka kerja sangat mengganggu :)

Anda masih dapat menerapkan aplikasi ke domain dan port yang berbeda dan Anda dapat menggunakan basePath yang sama untuk setiap env.

Sepertinya Anda akan baik-baik saja dengan solusi di mana "basePath" itu adalah bagian dari kode perutean Anda, sesuatu yang Anda sebutkan di awal - seperti subfolder di dalam pages direktori (btw, pendekatan itu akan memberi sinyal kepada pengembang yang dipilih basePath dengan cukup baik). Tetapi satu-satunya hal yang menghentikan Anda adalah bahwa jalur internal nextjs untuk aset _next tidak dapat dikonfigurasi.

Dan kedengarannya seperti masalah yang lebih sempit yang bisa kita selesaikan dengan efek samping jangka panjang yang lebih sedikit.

Dan itu bisa membawa kita lebih jauh, seperti jika kita dapat mengkonfigurasi assetPath per aset (misalnya dengan semacam peta next.config) - ini akan memungkinkan kita untuk berbagi aset antar aplikasi, yang akan meningkatkan kinerja, dan hal-hal lain.

Dan ada PR terbuka untuk fitur itu. ;) / cc @timneutkens sepertinya sudah waktunya untuk kembali ke anak anjing itu. :)

Jika Anda tidak akan menambahkan ini dalam waktu dekat, dapatkah kita mendapatkan contoh server.js berbasis ekspres ditambahkan ke readme yang melakukan ini dan berfungsi? Saya telah mencoba beberapa yang telah beredar dalam masalah ini tetapi tidak dapat membuatnya berfungsi. Terima kasih.

Hai @ccarse Saya memiliki garpu yang berfungsi yang sudah kami gunakan dalam produksi: https://github.com/panter/next.js/pull/2
Saya juga siap menginvestasikan waktu untuk membuka PR untuk fitur ini.
@timneutkens @alexindigo apakah ada cara lain untuk mengatasi masalah ini?
Jika kami tidak memerlukan konfigurasi basePath , dapatkah Anda memberi kami contoh minimal menggunakan assetPath ?

Perusahaan saya juga menentang ini.

Kami perlahan-lahan mengambil alih aplikasi lama, bagian demi bagian, dan menggantinya dengan Next.js.

Sebagai contoh yang disederhanakan:

| URL | Aplikasi |
| --- | --- |
| example.com | warisan |
| contoh.com/shop | berikutnya |
| example.com/search | warisan |
| example.com/members | berikutnya |

Itu berarti kami ingin semuanya diawali dalam setiap aplikasi Next.js ... Halaman, rute, aset, dll.

Perlu juga dicatat bahwa kami tidak menggunakan Now, jadi kami tidak dapat memanfaatkan perutean now.json . Kami memiliki penyeimbang beban kami sendiri yang berada di depan seluruh domain dan kemudian merutekan lalu lintas berdasarkan sub jalur.

Kami juga menggunakan server khusus (hapi), jadi alangkah baiknya jika kami dapat memanfaatkan apa pun yang dibuat di sini dalam server khusus juga.

Mungkin ada beberapa kombinasi pengaturan now.config.json atau beberapa penggunaan mikro-proxy yang dapat kita gunakan untuk mencapai hal yang sama ini, tetapi kita belum menemukan kombinasi yang tepat.

Kami mengalami, saya pikir, masalah yang sama dengan beberapa aplikasi Next.js yang diekspor secara statis yang dihosting di Now v2.

| URL | Aplikasi |
| - | - |
| example.com | berikutnya |
| example.com/dashboard | berikutnya |

Seperti yang diharapkan, aplikasi root berfungsi dengan baik. Segalanya menjadi serba salah di yang kedua. Saat ini kami membungkus next/link yang, dikombinasikan dengan assetPrefix , menyelesaikan sebagian besar masalah:

export default ({ children, href, ...rest }) => (
      <Link href={process.env.NODE_ENV === "production" ? `/dashboard${href}` : href} {...rest}>
        {children}
      </Link>
);

Namun, ini merusak prefetch karena kemudian mencoba mencari file .js di URL yang salah:

Solusi kami saat ini adalah menonaktifkan prefetch , yang tidak ideal.

Apa statusnya ini?

Juga mencari pembaruan tentang ini.

@timneutkens Saya siap menginvestasikan waktu untuk membuka PR jika komunitas tertarik. Kami sudah menggunakan solusi (https://github.com/panter/next.js/pull/1) dalam produksi dan kami sangat senang dengannya.

Kami juga membutuhkan solusi untuk ini

Kami akan segera memperkenalkan API baru yang akan membuat proposal ini menjadi usang.

Juga terkena dampaknya. Perlu menjalankan proyek berikutnya di bawah jalur subdirektori. Menantikan fitur resmi. Apakah ada ETA?

API

Jadi bagaimana kabarnya? : D

Harap jangan mengirim spam ke utas dan gunakan fitur GitHub 👍 pada masalah itu sendiri.

@timneutkens Dapatkah Anda memberikan info lebih lanjut? API apa yang akan membuat ini usang? Apa yang Anda anggap "segera"? Terima kasih.

Ini mungkin tidak sepenuhnya terkait dengan multi-zona tetapi dapat membantu ...

Saya memecahkan sesuatu yang mirip dengan ini dengan membuat server khusus dan menggunakan middleware proxy

misalnya: @Zertz
Harap dicatat: Anda masih perlu menyelesaikan masalah tautan - Sekali lagi, saya menyelesaikan ini dengan membuat komponen tautan dan meneruskan awalan ke aplikasi melalui konfigurasi dan jika ada prefiks, gunakan itu atau gunakan apa-apa, sama untuk gambar statis.

const proxy = require('http-proxy-middleware');

app.setAssetPrefix('/dashboard');

  // Express custom server
  // Proxy so it works with prefix and without...
  // So if asset prefix is set then it still works
  const server = express();
  server.use(
    proxy('/dashboard', {
      target: 'http://localhost:3000', 
      changeOrigin: true,
      pathRewrite: {
        [`^/dashboard`]: '',
      },
    }),
  );

Proposal yang saya sebutkan adalah # 7329

Proposal yang saya sebutkan adalah # 7329

@tokopedia
Bisakah Anda memberikan detail lebih lanjut tentang bagaimana hook yang diusulkan akan menyelesaikan masalah basepath kami?
Dan bagaimana dengan pengalihan router seperti Router.push('/about') apakah ini akan diganti dengan pengait juga?

Terima kasih atas waktunya 😏

Api router juga akan berubah, karena memerlukan komponen untuk ditautkan. Pada saat itu, Anda dapat menggunakan jalur relatif untuk url itu sendiri.

Adakah pembaruan tentang kapan kita bisa mendapatkan solusi atau setidaknya solusi untuk ini?

Gunakan 👍 pada masalah awal daripada memposting pembaruan apa pun.

@ MMT-LD Solusi Anda berfungsi untuk saya, tetapi sekarang di setiap klik Tautan atau peristiwa push Router, halaman dimuat ulang ☹️

Saya mencoba solusi @Zertz dan berhasil dengan sempurna!
Saya juga bisa memperbaiki masalah prefetch dengan menyalin file keluaran ke jalur yang telah diambil sebelumnya.
https://github.com/fand/MDMT/blob/master/scripts/copy-preload.js

... itu trik kotor, tapi tetap berhasil🤪

@bayu_joo

Sekarang di setiap klik Tautan atau peristiwa push Router, halaman dimuat ulang ☹️

Saya mengalami masalah ini tetapi tetap menggunakan parameter 'sebagai' pada tautan, jadi tautan mengarah ke file internal, tetapi 'sebagai' relatif terhadap jalur
misalnya:
<Link href={"/${item.link}"} as={"./${item.link}"}>

@bayu_joo

Solusi Anda berfungsi untuk saya, tetapi sekarang di setiap klik Tautan atau peristiwa push Router, halaman dimuat ulang ☹️

Inilah yang saya maksud. Ini dari ingatan .... tapi saya yakin Anda tidak bisa mendapatkan apa yang Anda butuhkan dari bawah.

// WithConfig component
import getConfig from 'next/config';

const { publicRuntimeConfig } = getConfig();

const WithConfig = ({ children }) =>
  children && children({ config: publicRuntimeConfig });

export default WithConfig;
// Extended Link component

 import React from 'react';
import PropTypes from 'prop-types';
import Link from 'next/link';
import { WithConfig } from '../WithConfig';
/* 
    <Link> component has two main props:
    href: the path inside pages directory + query string. e.g. /page/querystring?id=1
    as: the path that will be rendered in the browser URL bar. e.g. /page/querystring/1

*/

const NextLink = ({
  browserHref,
  pagesHref,
  whatever,
}) => {
  return (
    <WithConfig>
      {({ config: { pathPrefix } = {} }) => (
        <Link
          as={pathPrefix ? `${pathPrefix}${browserHref}` : browserHref}
          href={pagesHref}
          passHref
        >
          <a>{whatever}</a> // this bit is up to you - children or whatever
        </Link>
      )}
    </WithConfig>
  );
};

NextLink.propTypes = {
  browserHref: PropTypes.string.isRequired,
  pagesHref: PropTypes.string,
};

NextLink.defaultProps = {
  pagesHref: undefined,
};

export default NextLink;

Pemakaian:

import NextLink from '../NextLink'

<NextLink browserHref={`/page/1`} pagesHref={`/page?querystring=1`} whatever='I'm the link' />

Semoga berhasil: smiley:

Karena useLink RFC sekarang ditolak (# 7329) dan memiliki basePath dukungan akan sangat membantu kami, apakah proyek Next.js dengan senang hati menerima PR yang mengimplementasikannya? Saya bersedia melakukannya.

Melihat implementasi oleh @tomaswitek ini , tampaknya berjalan ke arah yang benar, yang paling penting membuat router menyadari basePath . Apakah ada hal-hal tidak jelas lainnya yang akan membuat basePath dukungan sulit?

Secara keseluruhan, menurut saya desainnya jelas, hanya satu variabel konfigurasi:

module.exports = {
  basePath: '/demo'
}

Interaksi dengan assetPrefix didefinisikan dengan baik di sini: https://github.com/zeit/next.js/issues/4998#issuecomment -414978297.


UPDATE : Saya juga berpikir apakah mungkin untuk menerapkan ini dengan membuat router khusus dan entah bagaimana menukar yang default tetapi tampaknya tidak mungkin, Next.js melakukan hardcode routernya, lihat misalnya di sini . Saya juga skeptis bahwa "hanya" mengganti router sudah cukup; fitur tersebut mungkin perlu didukung oleh Next.js secara keseluruhan.

Masalah ini sudah ada sejak 2017, apakah ada solusinya? Atau tanggapan resmi atas permintaan basePath kami?

Jadi setelah mencoba membuat ini berfungsi dengan kombinasi assetPrefix dan komponen khusus <Link> seperti yang disarankan di misalnya https://github.com/zeit/next.js/issues/4998#issuecomment -464345554 atau https://github.com/zeit/next.js/issues/4998#issuecomment -521189412, saya tidak percaya ini bisa dilakukan, sayangnya.

Mendefinisikan assetPrefix relatif mudah, seperti ini di next.config.js :

const assetPrefix = process.env.DEPLOYMENT_BUILD ? '/subdir' : '';

module.exports = {
  assetPrefix,
  env: {
    ASSET_PREFIX: assetPrefix,
  },
}

Langkah selanjutnya adalah komponen kustom Link . Ide pertama, yang diberikan misalnya di https://github.com/zeit/next.js/issues/4998#issuecomment -464345554, adalah memberi awalan href seperti ini (disederhanakan):

export default ({ children, href, ...rest }) => (
  <Link href={`${process.env.ASSET_PREFIX}${href}`} {...rest}>
    {children}
  </Link>
);

Seperti yang dilaporkan oleh orang lain di utas ini, ini menghentikan pengambilan karena permintaan tiba-tiba ke / subdir /_next/static/.../pages/ subdir /example.js - "subdir" lainnya seharusnya tidak ada di sana. Tetapi dengan komponen kustom Link , kita menyetel href ke /subdir/example , jadi tidak heran Next.js meminta bundel halaman pages/subdir/example.js .

Jadi oke, prefetching bermasalah tidak terdengar seperti akhir dunia (meskipun UX cukup jelek) tetapi di aplikasi kita, semuanya menjadi lebih buruk karena kita menggunakan perutean dinamis Next.js 9. Untuk itu, kita perlu mengatur as dengan benar sehingga evolusi komponen kustom Link terlihat seperti ini:

export default ({ children, href, as, ...rest }) => (
  <Link 
    href={`${process.env.ASSET_PREFIX}${href}`}
    as={`${process.env.ASSET_PREFIX}${as}`}
    {...rest}
  >
    {children}
  </Link>
);

Penggunaannya adalah:

<CustomLink href='/post/[id]' as='/post/1'>...</CustomLink>

yang akan diubah menjadi:

<Link href='/subdir/post/[id]' as='/subdir/post/1'>...</Link>

dan itu tidak berhasil untuk saya ketika diterapkan di Sekarang sama sekali - mencoba menavigasi ke https://deployment-id.now.sh/subdir/post/1 mengarah ke 404. Saya tidak sepenuhnya yakin mengapa, mungkin itu juga masalah dengan @now/next pembangun ( PEMBARUAN : ini karena https://github.com/zeit/next.js/pull/8426#issuecomment-522801831) tetapi pada akhirnya, kami membingungkan router Next.js ketika kami meminta /subdir/post/[id] component jika tidak ada file seperti itu di disk.

Ada contoh lain di utas ini, https://github.com/zeit/next.js/issues/4998#issuecomment -521189412, yang diawali hanya sebagai , bukan href, seperti ini (disederhanakan):

export default ({ children, href, as, ...rest }) => (
  <Link href={href} as={`${process.env.ASSET_PREFIX}${as}`} {...rest}>
    {children}
  </Link>
);

tapi itu akan memunculkan kesalahan ini di browser:

Nilai <Link> as tidak sesuai dengan nilai href . Ini tidak valid.

Ini masalah yang dilaporkan di https://github.com/zeit/next.js/issues/7488.

Setelah semua ini, saya tidak berpikir ada solusi sampai sesuatu seperti basePath didukung, yang akan saya bantu dengan senang hati.

@borekb Saya juga siap membantu seperti yang saya sebutkan beberapa kali sebelumnya. Semua solusi yang saya lihat sampai sekarang hanya menyelesaikan sebagian dari masalah. Saat ini kami menggunakan garpu next.js dalam produksi yang mengimplementasikan basePath.

Kami akan segera memperkenalkan API baru yang akan membuat proposal ini menjadi usang.

@tim Apakah masih demikian atau apakah proposal baru untuk API ditutup? https://github.com/zeit/next.js/issues/7329

Btw. besok tepat satu tahun saya membuka edisi ini 🎉

Salah satu ide yang relatif liar adalah memiliki halaman-halaman seperti src/pages dan kemudian menghubungkannya ke lokasi yang tepat. Sebagai contoh:

  • Untuk menerapkan ke myapp.example.com , saya akan menghubungkan src/pages ke pages
  • Untuk menerapkan ke example.com/myapp , saya akan menghubungkan src/pages ke pages/myapp

Dikombinasikan dengan komponen kustom <Link> dan assetPrefix , ini _could_ berfungsi tetapi saya tidak cukup berani untuk mencobanya 😄.

Ada pembaruan dengan itu?

Ada kemajuan dalam dukungan basePath ? :)

@bayu_joo

Sekarang pada setiap klik Tautan atau peristiwa push Router, halaman memuat ulang frowning_face

Saya mengalami masalah ini tetapi tetap menggunakan parameter 'sebagai' pada tautan, jadi tautan mengarah ke file internal, tetapi 'sebagai' relatif terhadap jalur
misalnya:
<Link href={"/${item.link}"} as={"./${item.link}"}>

Anda menyelamatkan hari saya! :)))

saya melakukan hal yang sama dengan Router.push(`/route`, `${process.env.BASE_PATH}route`);

@bayu_joo

Sekarang di setiap klik Tautan atau peristiwa push Router, halaman dimuat ulang ☹️

Saya mengalami masalah ini tetapi tetap menggunakan parameter 'sebagai' pada tautan, jadi tautan mengarah ke file internal, tetapi 'sebagai' relatif terhadap jalur
misalnya:
<Link href={"/${item.link}"} as={"./${item.link}"}>

Solusi ini tidak berfungsi dengan 9 perutean berbasis file berikutnya. /route/[id] , ${process.env.BASE_PATH}/route${id} membuat kesalahan ini

Komentar ini menjelaskan masalahnya dengan sangat baik.

Meskipun saya telah melihat beberapa orang membahas bagaimana solusi di sini merusak pengambilan awal. Bagi kami ada masalah lain yang lebih penting.

Dengan next9, menggunakan assetPrefix di href menghasilkan next _always_ melakukan rute server. Saya telah membuat repo reproduksi dalam edisi ini yang mendemonstrasikannya.

Ini pada dasarnya merusak cache Klien Apollo kami, karena dibuat ulang di setiap rute.

Saya pikir implementasinya membandingkan halaman yang mendasari href tanpa assetPrefix, ke rute berikutnya href (yang mencakup assetPrefix) - menghasilkan rute yang dalam.

misalnya Jika Anda berada di href /prefix/page (Halaman mendasari hanya /page ) dan berikutnya href rute yang /prefix/page/[id] (karena tanpa awalan itu akan 404) ini adalah rute yang sangat berbeda dan rute yang dangkal tidak mungkin.

Mencari solusi pada saat itu dengan rute ekspres

Saat digunakan komponen dengan href props yaitu basePath, prefetch tidak bekerja.
PLZ mendukung basePath dan prefetch, itu akan luar biasa

Saya benar-benar bisa menggunakan ini. Saya menjalankan beberapa aplikasi dari satu sumber server dan masing-masing dipisahkan menjadi web/appX/{next project files} . Akan sangat bagus untuk memiliki kontrol lebih besar atas basePath. Saya sudah menemukan solusi untuk saat ini, tetapi itu tidak terlalu bagus.

ekspor statis juga membutuhkan basePath 😊

sepertinya pekerjaan sukses 👏

{
  experimental:{
    basePath: '/some/dir',
  }
}

Sayangnya ini adalah batasan yang sangat buruk bagi kami :(

Kami memiliki semua aplikasi di belakang proxy terbalik sehingga jalur harus diawali (dalam contoh di bawah ini adalah awalan /auction-results )

Kami sudah menggunakan assetPrefix prefix - dan ini memungkinkan aplikasi berjalan dengan baik untuk permintaan sisi server.
Misalnya: mydomain.com/auction-results/ berfungsi dengan baik dengan menggunakan beberapa perutean ekspres seperti:

router.get(`/${appPrefix}/`, (req, res) => {
  nextApp.render(req, res, '/national', req.params);
});

Tetapi ketika kami mencoba dan melakukan navigasi sisi klien melalui next/link , misalnya:

Di mana /auction-results adalah awalan aplikasi, dan /national adalah halaman di ~pages/national

<Link href="/national" as="/auction-results/">
  <a>Goto National Page</a>
</Link>

Ini tidak melakukan apa-apa (klik hantu)

Memiliki link refresh halaman penuh kurang dari ideal.

Jika ada cara saya dapat membantu dengan ini, saya ingin sekali

Setiap pembaruan tentang ini ... tahun lalu sekitar waktu ini saya mengalami masalah ini. Sekarang setahun kemudian, saya mengerjakan aplikasi baru dan harus melakukan solusi yang sama yang saya lakukan tahun lalu ... agak mengkhawatirkan untuk reaksi 'siap produksi'. Basepaths harus menjadi fitur vanilla.

Setiap pembaruan tentang ini ... tahun lalu sekitar waktu ini saya mengalami masalah ini. Sekarang setahun kemudian, saya mengerjakan aplikasi baru dan harus melakukan solusi yang sama yang saya lakukan tahun lalu ... agak mengkhawatirkan untuk reaksi 'siap produksi'. Basepaths harus menjadi fitur vanilla.

Saya tidak yakin apa yang Anda harapkan dengan memposting ini.

Next.js sedang dikerjakan penuh waktu oleh tim saya (5 orang), dan kami mengerjakan banyak fitur pada waktu yang sama. Pada tahun lalu kami telah mengerjakan ini:

Secara efektif membuat aplikasi Next.js (baru dan yang sudah ada) secara signifikan lebih kecil, lebih cepat, dan lebih skalabel.

Jika Anda ingin menyuarakan "upvote" Anda untuk suatu fitur, Anda bisa. gunakan fitur 👍 di utas awal.

Saya sangat setuju basePath harus menjadi fitur bawaan. Itu sudah ada di peta jalan dan saya bahkan menulis PR awal, yang bisa Anda lihat dengan membaca kembali di utas.

Inilah PR: https://github.com/zeit/next.js/pull/9872

Jangan ragu untuk menghubungi [email protected] jika Anda ingin berkontribusi secara finansial untuk mewujudkan fitur ini.

Apa Status ini? kami sangat bergantung pada ini: /

Dukungan @Sletheren basePath masih eksperimental sekarang, gunakan dengan risiko Anda sendiri.

cf. https://github.com/zeit/next.js/pull/9872

Dukungan @Sletheren basePath saat ini masih eksperimental, gunakan dengan risiko Anda sendiri.

cf. # 9872

@martpie Saya sudah melihatnya, tapi untuk. kasus saya basePath bukan hanya satu, ini dapat berupa beberapa basePath, karena kami melayani aplikasi kami melalui "URL" yang berbeda dan menyiapkan basePath selama waktu pembuatan bukanlah suatu pilihan (meskipun ada untuk mendukung larik jalur daripada satu string)

@timneutkens Terima kasih atas pembaruannya. Apakah Anda akan berbaik hati memberikan pembaruan lain. Bagi kami ini adalah fitur utama dan kami perlu tahu ...

  1. Apakah ini hanya untuk perusahaan (referensi Anda untuk menghubungi bagian penjualan perusahaan menyebabkan gangguan)?

  2. Sepertinya sudah ada di peta jalan, menurut PR itu tidak akan dihapus lagi; dapatkah Anda memberikan beberapa indikasi apakah aman untuk mengembangkan fitur ini sekarang tanpa mendapatkan kejutan apa pun di bulan-bulan mendatang seperti versi open source yang lumpuh dan versi lain dengan dukungan penuh setelah kami bernegosiasi selama berminggu-minggu dengan beberapa staf penjualan acak tentang harga sewenang-wenang?

Saya memahami bahwa kalian bekerja pada banyak fitur dan setiap orang memiliki prioritasnya sendiri tetapi bahkan penyiapan yang lebih kecil perlu proxy. Selanjutnya, jalankan beberapa contoh dan berikan basePath per layanan. Sebelum kita sekarang mulai membangun beberapa layanan di Berikutnya kita perlu tahu seberapa besar kemungkinan dan segera fitur ini tersedia sebagai sumber terbuka penuh. Jika tidak, akan terlalu berisiko menginvestasikan lebih banyak waktu ke Next.

Terima kasih atas pengertian Anda dan menunggu umpan balik Anda.

FWIW, saya mendapatkannya sekarang berfungsi dan untuk orang lain mengemudi dengan:

Taruh ini di next.config.js :

module.exports = {
  experimental: {
    basePath: '/custom',
  },
}

Kemudian, saya perlu me-restart server dan mengatur middleware server web saya dengan benar:

Saya menangkap semua permintaan melalui jalur khusus, misalnya. app.use('/custom', (req, res...) => { ... dan kemudian (yang penting) saya perlu melakukan proxy ke URL sistem tempat Next berjalan (jadi alamat internal orkestrasi container Anda dan sekali lagi dengan path masing-masing jika Anda menggunakan http-proxy => mis. ... target: 'http://next:3000/custom ), jadi bukan hanya host tanpa jalur kustom. Jika Anda menggunakan http-proxy-middleware Anda tidak membutuhkan ini.

Rasanya cukup oke, saya harap fitur ini tidak memerlukan lisensi EE apa pun. Jika tim Anda membutuhkan bantuan untuk menjadikan fitur ini matang, mohon beri tahu kami, mungkin kami dapat membantu!

Sunting: Baru saja mencoba ini juga dengan mode produksi Next dan tampaknya berfungsi juga.

@timneutkens Terima kasih atas pembaruannya. Apakah Anda akan berbaik hati memberikan pembaruan lain. Bagi kami ini adalah fitur utama dan kami perlu tahu ...

  1. Apakah ini hanya untuk perusahaan (referensi Anda untuk menghubungi bagian penjualan perusahaan menyebabkan gangguan)?
  2. Sepertinya sudah ada di peta jalan, menurut PR itu tidak akan dihapus lagi; dapatkah Anda memberikan beberapa indikasi apakah aman untuk mengembangkan fitur ini sekarang tanpa mendapatkan kejutan apa pun di bulan-bulan mendatang seperti versi open source yang lumpuh dan versi lain dengan dukungan penuh setelah kami bernegosiasi selama berminggu-minggu dengan beberapa staf penjualan acak tentang harga sewenang-wenang?

Saya memahami bahwa kalian bekerja pada banyak fitur dan setiap orang memiliki prioritasnya sendiri tetapi bahkan penyiapan yang lebih kecil perlu proxy. Selanjutnya, jalankan beberapa contoh dan berikan basePath per layanan. Sebelum kita sekarang mulai membangun beberapa layanan di Berikutnya kita perlu tahu seberapa besar kemungkinan dan segera fitur ini tersedia sebagai sumber terbuka penuh. Jika tidak, akan terlalu berisiko menginvestasikan lebih banyak waktu ke Next.

Terima kasih atas pengertian Anda dan menunggu umpan balik Anda.

@ pe-s Saya pikir Anda salah paham tentang posting saya.

Tidak ada "versi perusahaan Next.js" untuk saat ini. Saya mengacu pada banyak kesempatan di mana perusahaan eksternal membayar untuk konsultasi guna membangun fitur seperti ini dalam rentang waktu yang lebih singkat. Misalnya, dukungan zona dibangun bekerja sama dengan Trulia.

Fitur ini sedang dikerjakan dan sedang dalam peta jalan. Semua fitur yang sedang dikerjakan adalah open-source, seperti yang saya katakan tidak ada versi perusahaan dari Next.js. Kami memiliki banyak prioritas pekerjaan berdampak tinggi pada peta jalan meskipun oleh karena itu mengapa saya merujuk untuk menghubungi [email protected] jika Anda memerlukan fitur ini secepat mungkin / untuk mendiskusikan dukungan perusahaan untuk Next.js.

@timneutkens tx untuk respon cepat dan bagus! Kemudian, kita bisa masuk semuanya :)
Pertahankan kerja bagus!

Dukungan Basepath tersedia di next@canary sekarang, tidak lagi eksperimental. Ini akan segera ada di saluran stabil.

Saya cukup terlambat untuk ini tetapi apakah Anda mempertimbangkan untuk menggunakan HTML aktual

Dukungan Basepath tersedia di next@canary sekarang, tidak lagi eksperimental. Ini akan segera ada di saluran stabil.

@timneutkens , terima kasih atas tambahan ini. Tahukah Anda kapan dukungan basePath non-eksperimental akan dirilis secara resmi?

Selain itu, ketika saya menyetel basePath, aset (terletak di folder publik) akan disajikan ke url yang sesuai seperti yang diharapkan. Tetapi, ketika saya mereferensikannya dalam kode saya, maka saya harus menambahkan jalur dasar ke src secara manual, karena jika tidak, mereka masih akan direferensikan dari jalur normal. Apakah ini penggunaan basePath yang diharapkan? Saya juga mencoba menggunakan assetPrefix, tetapi tidak ada efek apa pun yang dapat saya ketahui pada kode saya.

Contoh :

  1. menggunakan next v9.4.5-canary.24
  2. basePath disetel ke /alerts di next.config.js:
const basePath = '/alerts';
module.exports = {
  basePath: basePath,
  env: {
    BASE_PATH: basePath,
  },
};
  1. aset terletak di public/images/example.png
  2. Contoh penggunaan aset dalam komponen react:
const ExampleImage = () => (
  <img src={`${process.env.BASE_PATH}/images/example.png`} />
);

Dalam pengujian saya, itu tidak memperbarui url aset.

Saya memasang kenari terbaru:
npm install [email protected]

next.config.js

const isProd = process.env.NODE_ENV === 'production';

module.exports = {
  basePath: isProd ? '/example' : ''
}

Semua halaman dan link dimuat dengan benar:
http: // localhost : 3000 / example / posts / pra-rendering
http: // localhost : 3000 / example / posts / ssg-ssr
http: // localhost : 3000 / example / posts / pra-rendering

Namun gambar, favicon, dll. Tidak dipetakan:
http: // localhost : 3000 / favicon.ico 404
http: // localhost : 3000 / images / profile.jpg 404

Apakah ada yang menguji ini? Saya juga mencoba menggunakan assetPrefix, tetapi itu juga tidak berhasil.

Selain itu, saya bingung, mengapa tidak menggunakan fungsi browser bawaan untuk ini?
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base

Terima kasih telah melihat ini di pihak Anda juga @kmturley . Senang mengetahui itu bukan hanya aku.
@timneutkens , haruskah kita membuka kembali masalah ini / membuat masalah baru untuk bug ini?

Anda harus mengawali gambar secara manual. Anda bisa mendapatkan basePath menggunakan

const {basePath} = useRouter()

https://nextjs.org/docs/api-reference/next.config.js/cdn-support-with-asset-prefix

Next.js secara otomatis akan menggunakan prefiks Anda pada skrip yang dimuatnya, tetapi ini tidak berpengaruh apa pun pada folder publik;

Sekarang, saya menyadari ada banyak cara untuk menautkan ke file di / publik. misal <img/> <link/> ...
Apakah ini mengapa kita harus menentukan basePath secara manual ke masing-masing?

Jika ada komponen seperti di bawah ini yang tersedia, menurut saya akan menghemat waktu dan mengurangi kebingungan bagi banyak orang?

<WithinBasePath>
  {/* automatically fixes the path with basePath */}
  <img src="/logo.png" />
</WithinBasePath>

Menurut saya ini tidak pantas, tetapi inilah yang saya maksud.

// src/components/WithinBasePath/index.tsx

import React from "react"
import path from "path"
import { useRouter } from "next/router"
interface Props {}

const WithinBasePath: React.FC<Props> = (props) => {
  const { basePath } = useRouter()
  const children = [props.children].flatMap((c) => c) as React.ReactElement[]
  return (
    <>
      {children.map((child, key) => {
        let newChild = null

        switch (child.type) {
          case "img":
            newChild = React.createElement(child.type, {
              ...child.props,
              src: path.join(basePath, child.props.src),
              key,
            })
            break
          case "link":
            newChild = React.createElement(child.type, {
              ...child.props,
              href: path.join(basePath, child.props.href),
              key,
            })
            break
          default:
            newChild = React.createElement(child.type, {
              ...child.props,
              key,
            })
        }
        return newChild
      })}
    </>
  )
}
export default WithinBasePath

// pages/test.tsx

import React from "react"
import WithinBasePath from "@src/components/WithinBasePath"
interface Props {}

const test: React.FC<Props> = (props) => {
  return (
    <WithinBasePath>
      <img src="/123.jpg" />
      <link href="/abc.jpg" />
      <div>other element</div>
    </WithinBasePath>
  )
}
export default test

Bagi mereka yang mencoba menggunakan const {basePath} = useRouter() yang merupakan Hook, untuk bekerja dengan Kelas dan Komponen dan mendapatkan kesalahan ini:

Peringatan Panggilan Hook Tidak Valid

https://reactjs.org/warnings/invalid-hook-call-warning.html

Anda bisa membuatnya berfungsi menggunakan:

import { withRouter, Router } from 'next/router'

class Example extends Component<{router: Router}, {router: Router}> {
  constructor(props) {
    super(props)
    this.state = {
      router: props.router
    }
  }
  render() {
    return (
      <Layout home>
        <Head><title>Example title</title></Head>
        <img src={`${this.state.router.basePath}/images/creators.jpg`} />
      </Layout>
    )
  }
}
export default withRouter(Example)

Jika Anda ingin menggunakan basePath dengan penurunan harga, sepertinya Anda perlu melakukan pencarian dan penggantian di string:

const content = this.state.doc.content.replace('/docs', `${this.state.router.basePath}/docs`);
return (
<Layout>
  <Container docs={this.state.allDocs}>
    <h1>{this.state.doc.title}</h1>
    <div
      className={markdownStyles['markdown']}
      dangerouslySetInnerHTML={{ __html: content }}
    />
  </Container>
</Layout>
)

Anda harus mengawali gambar secara manual. Anda bisa mendapatkan basePath menggunakan

const {basePath} = useRouter()

Solusi ini tidak memperhitungkan gambar yang diimpor dalam file css atau scss. Apakah Anda memiliki solusi tentang cara menyetel jalur dasar saat mengimpor aset dari dalam file css atau scss?
Dengan solusi ini kita harus memastikan bahwa semua gambar diimpor baik melalui tag img, gaya sebaris, atau dalam tag gaya. Ini tidak ideal, karena akan membagi gaya Anda untuk diterapkan di banyak tempat.

@peetjvv Berikut adalah solusi suboptimal untuk menggunakan aset dengan basePath yang diawali di CSS. Buat, impor, dan tambahkan komponen <CSSVariables> di _app.tsx , yang memasukkan elemen <style> sebaris global yang berisi variabel CSS, yang kemudian dapat Anda gunakan di seluruh stylesheet Anda.

Misalnya pada pembukaan <body> membangun dan menyuntikkan variabel:

<style>
:root {
      --asset-url: url("${basePath}/img/asset.png");
}
</style>

Untuk mendapatkan basePath itu saya menggunakan pendekatan @kmturley dengan menggunakan withRouter .
Seperti inilah tampilan komponen itu:

import { withRouter, Router } from "next/router";
import { Component } from "react";

export interface IProps {
  router: Router;
}

class CSSVariables extends Component<IProps> {
  render() {
    const basePath = this.props.router.basePath;
    const prefixedPath = (path) => `${basePath}${path}`;
    const cssString = (value) => `\"${value}\"`;
    const cssURL = (value) => `url(${value})`;
    const cssVariable = (key, value) => `--${key}: ${value};`;
    const cssVariables = (variables) => Object.entries(variables)
      .map((entry) => cssVariable(entry[0], entry[1]))
      .join("\n");
    const cssRootVariables = (variables) => `:root {
      ${cssVariables(variables)}
    }`;

    const variables = {
      "asset-url": cssURL(
        cssString(prefixedPath("/img/asset.png"))
      ),
    };

    return (
      <style
        dangerouslySetInnerHTML={{
          __html: cssRootVariables(variables),
        }}
      />
    );
  }
}

export default withRouter(CSSVariables);
Apakah halaman ini membantu?
0 / 5 - 0 peringkat