Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSG includes hostname on build links at root directory #183

Open
efc opened this issue Nov 2, 2024 · 3 comments
Open

SSG includes hostname on build links at root directory #183

efc opened this issue Nov 2, 2024 · 3 comments

Comments

@efc
Copy link

efc commented Nov 2, 2024

Used statamic new to create a project named x including SSG. Set /resources/site.yaml default url to /foo. In other words, I am trying to generate a static site that is contained within the /foo folder of another host.

When I generate the static site I get a home page with the following...

        <link rel="preload" as="style" href="http://x.test/build/assets/site-9bd4acd3.css" /><link rel="modulepreload" href="http://x.test/build/assets/site-4ed993c7.js" /><link rel="stylesheet" href="http://x.test/build/assets/site-9bd4acd3.css" /><script type="module" src="http://x.test/build/assets/site-4ed993c7.js"></script>

These links have two problems. One is that they include the http://x.text host, and I plan to serve the static site from another host. The other is that they reference the build directory from the root of the server, and I expect (and need) all the static files to be in the site's /foo directory.

These links are generated from the layout.antlers.html template's vite tag...

        {{ vite src="resources/js/site.js|resources/css/site.css" }}

I also find the build directory at /storage/static/build.

What I expect is a site fully contained in the /storage/static/foo directory, with build at /storage/static/foo/build and links that do not include a host.

What all do I need to change in this plain new Statamic site to get this result?

@ssx
Copy link

ssx commented Nov 17, 2024

Also ran in to this today.

@efc
Copy link
Author

efc commented Nov 18, 2024

Here is how I am working around this problem for now. I really would rather the problem didn't exist, but there has not been any response here for a few weeks, so I had to work around this somehow. I've added this code to the boot() method of the AppServiceProvider class in my /app/Providers/AppServiceProvider.php file...

        SSG::after(function () {
            $base = rtrim(config('statamic.ssg.base_url'), '/'); // remove trailing slash
            $current_site = (string)Site::current();
            $site_url = rtrim(Site::config()[$current_site]['url'], '/'); // remove trailing slash
            $dest = rtrim(config('statamic.ssg.destination'), '/') . $site_url; // no trailing slash

            $processed_count = $updated_count = 0;

            echo "Rewriting absolute URLs to remove server name\n";

            $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dest));

            foreach ($iterator as $fileInfo) {
                if ($fileInfo->isFile() && $fileInfo->getExtension() === 'html') {
                    $filePath = $fileInfo->getPathname();
                    $htmlContent = file_get_contents($filePath);

                    $dom = new \DOMDocument();
                    // suppress errors due to malformed HTML
                    libxml_use_internal_errors(true);
                    $dom->loadHTML($htmlContent);
                    libxml_clear_errors();

                    $checks = [
                        'a' => 'href',
                        'link' => 'href',
                        'img' => 'src',
                        'script' => 'src',
                    ];

                    foreach ($checks as $tag => $attribute) {
                        $elements = $dom->getElementsByTagName($tag);
                        foreach ($elements as $element) {
                            /** @disregard P1013 Undefined method */
                            $link = $element->getAttribute($attribute);
                            // there could probably be a more sophisticated check for absolute URLs
                            if (strpos($link, $base) === 0) {
                                /** @disregard P1013 Undefined method */
                                $element->setAttribute($attribute, substr($link, strlen($base)));
                                $updated_count++;
                            }
                        }
                    }

                    $modifiedHtml = $dom->saveHTML();
                    file_put_contents($filePath, $modifiedHtml);

                    $processed_count++;
                }
            }

            echo "Processed $processed_count HTML files, rewrote $updated_count URLs\n";
        });

This swoops in after SSG has done its thing to rewrite all the URLs to remove the hostname if it matches the base URL of the Statamic site.

I am pretty new to Statamic so please be very skeptical of this code and do let me know how it could be improved.

@efc
Copy link
Author

efc commented Nov 23, 2024

I learned there is an even simpler solution to this problem. Simply add ASSET_URL=/ to the .env file to tell Vite that it should use / as the custom base URL when building the site.

Note, this will not change anything when using npm run dev, but it will fix the site when using npm run build, so just make sure to do a real build of the site before using SSG to export it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants