almostnode 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "almostnode",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Node.js in your browser. Just like that.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -102,4 +102,4 @@
102
102
  "vite": "^5.4.0",
103
103
  "vitest": "^4.0.18"
104
104
  }
105
- }
105
+ }
@@ -816,6 +816,11 @@ export class NextDevServer extends DevServer {
816
816
  return this.serveNextShim(pathname);
817
817
  }
818
818
 
819
+ // Serve page components for client-side navigation
820
+ if (pathname.startsWith('/_next/pages/')) {
821
+ return this.servePageComponent(pathname);
822
+ }
823
+
819
824
  // Static assets from /_next/static/*
820
825
  if (pathname.startsWith('/_next/static/')) {
821
826
  return this.serveStaticAsset(pathname);
@@ -895,6 +900,28 @@ export class NextDevServer extends DevServer {
895
900
  return this.notFound(pathname);
896
901
  }
897
902
 
903
+ /**
904
+ * Serve page components for client-side navigation
905
+ * Maps /_next/pages/index.js → /pages/index.jsx (transformed)
906
+ */
907
+ private async servePageComponent(pathname: string): Promise<ResponseData> {
908
+ // Extract the route from /_next/pages/about.js → /about
909
+ const route = pathname
910
+ .replace('/_next/pages', '')
911
+ .replace(/\.js$/, '');
912
+
913
+ // Resolve the actual page file
914
+ const pageFile = this.resolvePageFile(route);
915
+
916
+ if (!pageFile) {
917
+ return this.notFound(pathname);
918
+ }
919
+
920
+ // Transform and serve the page component as a JS module
921
+ // Use the actual file path (pageFile) for both reading and determining the loader
922
+ return this.transformAndServe(pageFile, pageFile);
923
+ }
924
+
898
925
  /**
899
926
  * Handle API route requests
900
927
  */
@@ -1837,30 +1864,63 @@ export class NextDevServer extends DevServer {
1837
1864
  <script type="module">
1838
1865
  import React from 'react';
1839
1866
  import ReactDOM from 'react-dom/client';
1840
- import Page from '${pageModulePath}';
1841
1867
 
1842
- // Handle client-side navigation
1843
- function App() {
1844
- const [currentPath, setCurrentPath] = React.useState(window.location.pathname);
1868
+ const virtualBase = '${virtualPrefix}';
1845
1869
 
1846
- React.useEffect(() => {
1847
- const handlePopState = () => {
1848
- setCurrentPath(window.location.pathname);
1849
- // Defer reload outside React's update cycle
1850
- setTimeout(() => window.location.reload(), 0);
1851
- };
1870
+ // Convert URL path to page module path
1871
+ function getPageModulePath(pathname) {
1872
+ let route = pathname;
1873
+ if (route.startsWith(virtualBase)) {
1874
+ route = route.slice(virtualBase.length);
1875
+ }
1876
+ route = route.replace(/^\\/+/, '/') || '/';
1877
+ const modulePath = route === '/' ? '/index' : route;
1878
+ return virtualBase + '/_next/pages' + modulePath + '.js';
1879
+ }
1852
1880
 
1853
- window.addEventListener('popstate', handlePopState);
1854
- return () => window.removeEventListener('popstate', handlePopState);
1881
+ // Dynamic page loader
1882
+ async function loadPage(pathname) {
1883
+ const modulePath = getPageModulePath(pathname);
1884
+ try {
1885
+ const module = await import(/* @vite-ignore */ modulePath);
1886
+ return module.default;
1887
+ } catch (e) {
1888
+ console.error('[Navigation] Failed to load:', modulePath, e);
1889
+ return null;
1890
+ }
1891
+ }
1892
+
1893
+ // Router component
1894
+ function Router() {
1895
+ const [Page, setPage] = React.useState(null);
1896
+ const [path, setPath] = React.useState(window.location.pathname);
1897
+
1898
+ React.useEffect(() => {
1899
+ loadPage(path).then(C => C && setPage(() => C));
1855
1900
  }, []);
1856
1901
 
1902
+ React.useEffect(() => {
1903
+ const handleNavigation = async () => {
1904
+ const newPath = window.location.pathname;
1905
+ if (newPath !== path) {
1906
+ setPath(newPath);
1907
+ const C = await loadPage(newPath);
1908
+ if (C) setPage(() => C);
1909
+ }
1910
+ };
1911
+ window.addEventListener('popstate', handleNavigation);
1912
+ return () => window.removeEventListener('popstate', handleNavigation);
1913
+ }, [path]);
1914
+
1915
+ if (!Page) return null;
1857
1916
  return React.createElement(Page);
1858
1917
  }
1859
1918
 
1919
+ // Mark that we've initialized (for testing no-reload)
1920
+ window.__NEXT_INITIALIZED__ = Date.now();
1921
+
1860
1922
  ReactDOM.createRoot(document.getElementById('__next')).render(
1861
- React.createElement(React.StrictMode, null,
1862
- React.createElement(App)
1863
- )
1923
+ React.createElement(React.StrictMode, null, React.createElement(Router))
1864
1924
  );
1865
1925
  </script>
1866
1926
  </body>