swashata / wp-webpack-script

💥🔥📦👩‍💻 An easy to use, pre configured, hackable webpack setup & development server for WordPress themes and plugins.
https://wpack.io
MIT License
408 stars 57 forks source link

Dynamic import fails when I start production builds #1184

Closed marcof-git closed 3 years ago

marcof-git commented 3 years ago

Hi, i have an issue when building for production with 'run build' and using dynamic import().

If I use the static import all works: import {featureBlock} from "../../blocks/featureBlock/featureBlock";

When i try to use dynamic import and lunch 'start' livesync all works. But if i lunch 'build' for production the console print this error: bootstrap:126 Uncaught (in promise) ChunkLoadError: Loading chunk 0 failed. (error: http://dev.palazzospinola.beniculturali.it/home/undefinedcore/feature-block-d7b74d18.js)

the dynamic import is like this:

main.js import { scripts } from '../../../../plugins/ett-core-blocks/assets/scripts/scripts.js';

scripts.js

//import {featureBlock} from "../../blocks/featureBlock/featureBlock"; --> commented for the test
document.addEventListener("DOMContentLoaded", () => {
  const featuredBlockDetector = document.querySelector('.feature-block');
  if (featuredBlockDetector) {
    import(/* webpackChunkName: "feature-block" */'../../blocks/featureBlock/featureBlock').then((ok)=>{
      console.log('feature block loaded');
    });
  }
});

the project is like this:

module.exports = {
  // Project Identity
  appName: 'ettCoreTheme',
....
files: [{
    name: 'core',
    entry: {
      theme: ['./assets/styles/main.scss', './assets/scripts/main.js']
    },
    webpackConfig: (config, merge, appDir, isDev) => {
      let customRules = {
        plugins: [
          new webpack.ProvidePlugin({
            Popper: ['popper.js', 'default'],
          }),
          new WriteFilePlugin({
            test: /\.svg$/
          })
        ],
        module: {
          rules: [
            {
              test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
              use: [
                {
                  loader: fileLoader,
                  options: getFileLoaderOptions(
                    appDir,
                    isDev,
                    false
                  ),
                }
              ]
            },
          ],
        },
      };
      return merge(config, customRules);
    },
  }],
  outputPath: 'dist',
  hasReact: false,
  hasSass: true,
  hasLess: false,
  hasFlow: false,
  externals: {
    jquery: 'jQuery',
  },
  alias: undefined,
  errorOverlay: true,
  optimizeSplitChunks: true,
  watch: ['./(templates|lib)/**/*.php','./*.php'],
  packageFiles: ['inc/**', 'vendor/**', 'dist/**', '*.php', '*.md', 'readme.txt', 'languages/**', 'layouts/**', 'LICENSE', '*.css', ],

  packageDirPath: 'package',
  useBabelConfig: true,

in the babel config i put:

module.exports = function(api) {
  api.cache(true);
  return {
    presets: [
      ["@babel/preset-env", {
        "useBuiltIns": "entry",
        "corejs": 3
      }]
    ]
  };
}

In the php:

$enqueue = new \WPackio\Enqueue('ettCoreTheme', 'dist', '1.0.0', 'theme', __FILE__);
  $GLOBAL_ASSETS = $enqueue;
  $manifest = $enqueue->getManifest('core');
  $config = [
    'js' => true,
    'css' => true,
    'js_dep' => [],
    'css_dep' => [],
    'in_footer' => true,
    'media' => 'all',
  ];
  $assets = $enqueue->getAssets('core', 'theme', $config);

  $jses = $assets['js'];
  $csses = $assets['css'];

  foreach ($jses as $js) {
    if ($config['js']) {
      wp_enqueue_script($js['handle'], $js['url'], ['jquery_slim', 'underscore'], '1.0.0', true);
    }
  }

Any help? Thanks

swashata commented 3 years ago

Hi,

When you create an instance of \WPackio\Enqueue it automatically hooks to WordPress (both front-end and admin) to print the needed script for things like dynamic imports to work. You can see it here

https://github.com/swashata/wpackio-enqueue/blob/master/inc/Enqueue.php#L121

My guess is, the way you are instantiating is either after admin_print_scripts or somehow this is not fired at all.

marcof-git commented 3 years ago

Hey thanks for the reply. I instantiate the scripts with:

add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\assets');

and for the admin:

add_action('admin_enqueue_scripts', __NAMESPACE__ . '\\ett_enqueue_custom_admin_style');

In the usual wordpress way. Is there any different way that i should use with your script? With a different action?

If I don't use dynamic import() all works: the dev server and the production build.

Maybe is because i put the scripts in "footer" mode or did I enter deps? See [jquery_slim and underscore]

edit: just for learn more: i use to put in var -- $enqueue = new \WPackio\Enqueue('ettCoreTheme', 'dist', '1.0.0', 'theme', __FILE__); then i cycle the assets with

$assets = $enqueue->getAssets('core', 'theme', $config);
$jses = $assets['js'];
foreach ($jses as $js) {
    if ($config['js']) {
      wp_enqueue_script($js['handle'], $js['url'], ['jquery_slim', 'underscore'], '1.0.0', true);
    }
  }
marcof-git commented 3 years ago

Hey, I tried this too: but the result is the same.

in the assets function() init by the wp_enqueue_scripts action -->

$enqueue = new \WPackio\Enqueue('ettCoreTheme', 'dist', '1.0.0', 'theme', __FILE__);
$config = [
    'js' => true,
    'css' => true,
    'js_dep' => ['jquery_slim', 'underscore'],
    'css_dep' => [],
    'in_footer' => true,
    'media' => 'all',
  ];
  $enqueue->enqueue('core', 'theme', $config);

edit: just and update, I tried to put scripts in the head -> not working. bootstrap:126 Uncaught (in promise) ChunkLoadError: Loading chunk 0 failed. (error: http://dev.palazzospinola.beniculturali.it/undefinedcore/featureBlock-7a767946.js)

marcof-git commented 3 years ago

Hi, I used the guide here https://wpack.io/guides/using-wpackio-enqueue/#why-call-it-early and it doesn't seem to work. For a quick fix instead of wp_enqueue_scripts I used the wp_loaded hook and there are no errors. But I'm not sure it's the correct way, especially for dependency management.

swashata commented 3 years ago

Hi,

wp_enqueue_scripts is called after wp_head so when you instantiate WPackio\Enqueue in wp_enqueue_scripts it will fail. wp_loaded on the other hand is called before wp_head so it works just fine.

You can instantiate WPackio\Enqueue in init or wp_loaded and call $enqueue->enqueue() on wp_enqueue_scripts, that should also work.

marcof-git commented 3 years ago

Hi,

thank you for your help, now is working fine.

function.php
function initWpPack()
{
  Pack::init();
}
add_action('init', __NAMESPACE__ . '\\initWpPack');

a Class
class Pack
{
  private static $assets;
  static function init()
  {
    if (self::$assets) {
      return;
    }
    self::$assets = new \WPackio\Enqueue('CoreTheme', 'dist', '1.0.0', 'theme', __FILE__);
  }
  static function getPack()
  {
    return self::$assets;
  }
}

then within the wp_enqueue_scripts

$assetsQueue = Pack::getPack();
$assetsQueue->enqueue('core', 'theme', $config);