Enqueueing a script

Hey Everyone!

I’ve been searching around and can’t find quite the answer I am looking for. I am working on creating a mobile nav that requires a new JS file to be enqueued. I imported it at the top of the app.js file but when I call the function in my new file from an onclick it says it is not defined. When I look through the final output js file the function is not in there either. I feel like I am probably missing something, but I am not sure what. Thanks in advance for any help!

~Charlie

Below is my code.

app.js

import {domReady} from '@roots/sage/client';
import './mobile-nav';

/**
 * app.main
 */
const main = async (err) => {
  if (err) {
    // handle hmr errors
    console.error(err);
  }

  // application code
};

/**
 * Initialize
 *
 * @see https://webpack.js.org/api/hot-module-replacement
 */
domReady(main);
import.meta.webpackHot?.accept(main);

mobile-nav.js

function toggleMobileNav() {
    alert('TOGGLE!!!');
}

header.blade.php

<header class="banner my-8">

  <div class="hidden md:inline-block lg:inline-block w-full">
    <div class="grid grid-cols-3">

      <div class="banner-logo">
        <a class="banner-logo__link" href="{{ home_url('/') }}">
          <img src="@asset('images/HigherLogic_logo_stacked_160.png')">
        </a>
      </div>

      <div class="banner-nav col-span-2 mx-8">
        @if (has_nav_menu('primary_navigation'))
          <nav class="nav-primary" aria-label="{{ wp_get_nav_menu_name('primary_navigation') }}">
            {!! wp_nav_menu(['theme_location' => 'primary_navigation', 'menu_class' => 'nav', 'echo' => false]) !!}
          </nav>
        @endif
      </div>

    </div>
  </div>

  <div class="inline-block md:hidden lg:hidden w-full">
    <div class="grid grid-cols-3">

      <div class="mobile-nav flex items-center">
        @if (has_nav_menu('primary_navigation'))
          <div id="mobile-nav-button" class="mobile-nav-button text-3xl mx-8 text-thrive-text-gray cursor-pointer" onclick="toggleMobileNav()">
            <i class="fa-solid fa-bars"></i>
          </div>
          <div class="mobile-nav__wrapper hidden">
            <nav class="nav-mobile" aria-label="{{ wp_get_nav_menu_name('primary_navigation') }}">
              {!! wp_nav_menu(['theme_location' => 'primary_navigation', 'menu_class' => 'nav', 'echo' => false]) !!}
            </nav>
          </div>
        @endif
      </div>

      <div class="mobile-logo flex justify-center">
        <a class="mobile-logo__link" href="{{ home_url('/') }}">
          <img src="@asset('images/HigherLogic_logo_stacked_160.png')">
        </a>
      </div>

    </div>
  </div>

</header>

If you want to import something, you need to export it first: export - JavaScript | MDN

Ok, so if I do that, I can get it to work with the following.

app.js

import {domReady} from '@roots/sage/client';
import { toggleMobileNav } from './mobile-nav';

/**
 * app.main
 */
const main = async (err) => {
  if (err) {
    // handle hmr errors
    console.error(err);
  }

  // application code
};

/**
 * Initialize
 *
 * @see https://webpack.js.org/api/hot-module-replacement
 */
domReady(main);
import.meta.webpackHot?.accept(main);

$( document ).ready(function() {
  $('.mobile-nav-button').click(toggleMobileNav);
});

mobile-nav.js

function toggleMobileNav() {
    alert('TOGGLE!!!');
}

export { toggleMobileNav };

But the thing that bothers me about this is I still have to add code (besides the import) to the app.js. Is there a way to include mobile-nav.js so that it gets compiled into the final app.js file during the build and I don’t have to put any of my logic in app,js?

Why does this bother you?

So far as I understand it, this is counter to the intent of the import/export module concept and the way Webpack interacts with these things: A module is not meant to do anything on its own–it’s a collection of code that can be used by whatever imports it. This is how Webpack can do things like tree-shaking and other optimization stuff. You could export more logic (i.e. wrap your whole document ready logic in a function you export), which would reduce the amount of logic you need to add to app.js.

Got it, that makes more sense. I guess I just wasn’t sure if adding logic to app.js was bad practice. Thanks for your help!