Uncaught SyntaxError: expected expression, got '<'

I have build a project using Sage 10 and it’s on production. Thigs are going fine both on staging site and prouduction one, but I have problems locally.

Whenever I build my assets using yarn dev (or event yarn build), there seems to be a problem because they are not loaded when I open the page.

The script from “https://local.test/dev/public/app/themes/local-theme/public/resources_scripts_components_ShopSectionSlider_js.js” was loaded even though its MIME type (“text/html”) is not a valid JavaScript MIME type.

Uncaught SyntaxError: expected expression, got '<'

ChunkLoadError: Loading chunk resources_scripts_components_ShopSectionSlider_js failed.

On the Network tab, all the font and JS files are of type HTML.

This is my Bud config (v5.5.0):

const path = require('path')
require('dotenv').config({ path: path.resolve(__dirname, '../../../.env') })

const SVGSpritemapPlugin = require('svg-spritemap-webpack-plugin')
const ImageminWebpWebpackPlugin = require('imagemin-webp-webpack-plugin')

/**
 * @typedef {import('@roots/bud').Bud} bud
 *
 * @param {bud} config
 */

module.exports = async (app) => {
  app
    /**
     * Application entrypoints
     *
     * Paths are relative to your resources directory
     */
    .entry({
      app: ['@scripts/app.js', '@styles/app.scss']
    })

    /**
     * These files should be processed as part of the build
     * even if they are not explicitly imported in application assets.
     */
    .assets([app.path('src', 'images')])
    .assets([app.path('src', 'fonts')])

    /**
     * These files will trigger a full page reload
     * when modified.
     */
    .watch('resources/views/**/*', 'app/**/*')

    /**
     * Define the public path for dynamically imported assets.
     *
     * I am defining it an .env file and accessing it with `bud.env`.
     */
    .define({
      ASSET_PATH: JSON.stringify(process.env.ASSET_PATH)
    })

    .setPublicPath('')

    /**
     * Target URL to be proxied by the dev server.
     *
     * This is your local dev server.
     */
    .proxy(process.env.WP_HOME)

    .use(
      new SVGSpritemapPlugin('resources/sprite/*.svg', {
        output: {
          filename: 'spritesheet.svg',
          chunk: { keep: true },
          svgo: false
        }
      })
    )

    .use(new ImageminWebpWebpackPlugin())

    .postcss.setPlugin(
      'postcss-color-mod-function',
      require.resolve('postcss-color-mod-function')
    )
    .postcss.setPlugin('postcss-pxtorem', require.resolve('postcss-pxtorem'))

    /**
     * Development URL
     */
    .serve(`${process.env.WP_HOME}:3000`)
}

I load chunks asynchronously:

async importComponents(componentName) {
    return await import(`./components/${componentName}`)
  }

I use Valet for the local server.

hey @erip2 I ran into a similar issue recently and solved it with webpack magic comments to exclude PHP from the imports

async importComponents(componentName) {
    return await import(
        /* webpackExclude: /.php$/ */
        `./components/${componentName}`
    );
  }

hope that helps

Hey @slowrush , thanks for your answer!

Unfortunately, this didn’t fix my case. I even cleared the bud cache (yarn bud clean), but still the same.

Ah just noticed you’re not accessing via the webpack dev server ie. http://localhost.test:3000/. I think you either need to have that running or run yarn build to access via the host domain https://local.test/

I hope I’m wrong as having the same/similar issue currently (posted a Q on the Discord server earlier today to see if I’m doing something silly or if this is expected with webpack/hmr).

If you get an answer from Discord, it would be very helpful if post it here also.

I noticed that this problem occurs even in a new fresh project.
The assets are loaded fine on dev internal server (0.0.0.0:3000) but don’t work on proxy. I may open an issue about this.

The thing in my case is that for some reason I can’t open the dev on my project; it just redirects to the proxy URL or it doesn’t open at all.

yeah sounds like you’re having the exact same issue I had - annoyingly Valet adds a redirect from HTTP → HTTPS when using the secure command.

Option 1

Manually update the valet nginx conf ~/.config/valet/Nginx/example.test so you’re able to access the site over HTTP + HTTPS or run valet unsecure example to remove https entirely.

Option 2

Add certificates to the bud/webpack server.

  const domain = 'example.test';

  bud.serve(`https://${domain}`, {
    key: `${process.env.HOME}/.config/valet/Certificates/${domain}.key`,
    cert: `${process.env.HOME}/.config/valet/Certificates/${domain}.crt`,
  });

But I haven’t managed to get this working yet :sob: the same certs work perfectly with BrowserSync server so no idea what’s going on there?

Added an issue to track on the Bud repo

Cool, thanks!

Just wanted to add that in my case even with yarn build the assets are not loaded, the same error occurs as in yarn dev.

Another update here!

@slowrush Yeap, you were right here:

I did unsecure it since the second option didn’t work for me either.

My setup for dynamic js is inspired by this.
So, I have a publicPath.js file inside scripts folder which has this line:

__webpack_public_path__ = ASSET_PATH

I import this file in the main entry app.js and that’s what made dynamic imports work (in staging and production at least).
I removed this import declaration and now the JS files are working correctly on the dev server.

So, it means that I need to remove this line working locally, but don’t forget it to push it, because it would break the scripts on production.

Still, I can’t see the SVGs because they are from the proxy link eg: http://local.test

Security Error: Content at http://localhost:55871/ may not load data from http://local.test/app/themes/local-theme/public/spritesheet.svg.

I have used @asset to show the SVGs files. Also, the path is wrong.

@slowrush Out of curiosity, can you share what is your setup for Bud and JS that you use to load components dynamically?

I am using Bud 5.

I’ve had to put dynamic imports on the back burner because of this issue + a tight deadline.

Switched back to importing assets per ACF block via Roots\bundle (bundle('block-name')->enqueue();) + use browser-sync for live reload for the time being. If I make any progress I’ll be sure to post back here.

I know a fair few folks have solutions working, hopefully, they’ll follow up but I’ve hit a few too many walls :tired_face:

dynamic imports are pretty simple.

make sure your publicPath is set in your bud config:

bud.setPublicPath(`/app/themes/sage/public/`)

In your application code you can import dynamically:

// test.js
console.log('test loaded')
// app.js
const main = async () => {
  const condition = document.querySelector(`.foo`)
  if (condition) {
    await import('./test.js')
  }
}

main()

It works for css as well:

// test.css
body {
  background: black;
}
// app.js
const main = async () => {
  const condition = document.querySelector(`.foo`)
  if (condition) {
    await import('./test.css')
  }
}

main()

It’s a little weird to do a dynamic import on css (IMO). I’d prefer to load the css in a js module and dynamically import that:

// test.css
body {
  background: black;
}
// test.js
import './test.css'

console.log('test loaded')
// app.js
const main = async () => {
  const condition = document.querySelector(`.foo`)
  if (condition) {
    await import('./test.js')
  }
}

main()

Another example I just tested on vanilla sage. This one will only load the css to change the page background if ?condition=true is appended to the URL:

// resources/scripts/app.js
const init = async () => {
  let params = new URL(document.location.toString()).searchParams;
  let condition = params.get('condition');

  if (condition) await import('./test.js');
};

init();
// resources/scripts/test.js
import '@styles/test';

console.log('test loaded');
/** resources/styles/test.css */
body {
  background: black;
}
1 Like

There is too much going on in this topic. You should make a separate topic for any problems with SSL certificates.

And the dynamic JS file loads correctly on the proxy server?

(Or is this more a response to slowrush?)

If you run that code with yarn bud dev the code will work on the dev server.
If you run that code with yarn bud build the code will work on the proxy (and in staging, production, etc.)

The roots.io frontend uses this exact approach.

Thanks for you detailed answers.

I tried what you wrote above in a new sage theme with bedrock, but in the yarn build it still doesn’t seem to work.

.setPublicPath('/app/themes/eri-test/public/')

but I get this error

ChunkLoadError: Loading chunk 457 failed. (missing: http://bedrock.test/app/themes/eri-test/public/js/dynamic/457.js)

which is essentially the error of this thread and the one that slowrush opened the Github issue.

I don’t know what’s up with that.

  • Does /app/themes/eri-test/public/js/dynamic/457.js exist on disk?
  • Is /app/themes/eri-test/public/ the actual public path?

Dynamic imports just work out of the box. There is no reason to set anything like ASSET_PATH or use any webpack magic comments to use them. I don’t doubt that something isn’t working for you and maybe I just don’t understand the question.

If you want to use an image you can just import it:

import { domReady } from "@roots/sage/client";
import test from "@images/test.png";

const main = async () => {
  await import("./test.js");

  document.querySelector("#app").innerHTML = `
  <div>
    <img src="${test}" />
  </div>`;
};

domReady(main);
import.meta.webpackHot?.accept(console.error);

Ok, I created a new sage theme (since I mistakenly deleted the current one I was using for tests) and now it’s working as you said.

Still, the situation in my current project is not resolved by this. After days of trying to debug this issue, I still haven’t figured it out.

I have pasted my bud.config.js file in the thread starter.

If I try to set .setPublicPath() as you propose, no asset is loaded because the final link is wrong eg
https://local.test/app/themes/local-theme/public/dev/public/app/themes/local-theme/public/app.6e4d64.css

while if I let it empty, the assets are loading ok, but not the chunks:

ChunkLoadError: Loading chunk 570 failed.
(missing: http://local-site.test/570.9361df.js)

Maybe my project is messy and you guys can’t reproduce it, so I’ll have to spend more time on it :confused:

p.s. I tried to upgrade Bud from 5 to 6 (following this), but I got this error when trying to build the assets:

error [err_require_esm]: require() of es module ./node_modules/chalk/source/index.js
Probably will open a new issue if this persist.

I think it’s because you are defining ASSET_PATH. Don’t do that.

The second issue is because you are trying to require chalk somehow. I’m not sure why that is but I don’t think it’s a problem with bud.js. I don’t think I will be able to help you without a repo that reproduces the issue.

Hello again @kellymears !

Sorry to disturb again with this issue, but I think I finally managed to reproduce it in a fresh theme.

Here you go: GitHub - erip2/eri-sage-test

This theme is taken from here Release v10.1.0 · roots/sage · GitHub because in the current project I still use Bud v5.5.0.

You can install it and try: yarn dev and yarn build.

In the yarn dev case things work fine.
In the yarn build case there are errors because assets are not found:

GET http://bedrock.test/app/themes/eri-5.5.0/public/app/themes/eri-5.5.0/public/app.488aeb.js
[HTTP/1.1 404 Not Found 324ms]

If you set the publicPath to empty (.setPublicPath("")), on yarn dev things are working fine, but on yarn buildUncaught (in promise) ChunkLoadError: Loading chunk 806 failed.

I test the dev on bedrock.test:3000 and build on bedrock.test

Thank you!

I’m sorry, but v5.5.0 was released 236 days ago; you should update. There have been 496 commits since this code was released.

Bump everything to 6.5.3 and replace @wordpress/browserslist-config with @roots/browserslist-config and you should be good.

{
  "name": "sage",
  "private": true,
  "browserslist": [
    "extends @roots/browserslist-config"
  ],
  "engines": {
    "node": ">=16.0.0"
  },
  "scripts": {
    "dev": "bud dev",
    "build": "bud build",
    "translate": "npm run translate:pot && npm run translate:js",
    "translate:pot": "wp i18n make-pot . ./resources/lang/sage.pot --ignore-domain --include=\"app,resources\"",
    "translate:js": "wp i18n make-json ./resources/lang --pretty-print"
  },
  "devDependencies": {
    "@roots/bud": "6.5.3",
    "@roots/bud-tailwindcss": "6.5.3",
    "@roots/sage": "6.5.3"
  }
}
1 Like