Webpack未将资产捆绑到输出的bundle.js文件中。

huangapple go评论60阅读模式
英文:

Webpack not bundling assets with output bundle.js file

问题

以下是您要翻译的代码部分:

"I am using Webpack to pack static javascript files with folders and assets into a single output bundle.js file. The bundle.js file is then taken out from the original codebase and statically hosted in the backend server. The problem is that the assets are not bundled within the bundle.js file. When I try to display the publicly hosted index.js url in the frontend, I get the error message saying

GET http://127.0.0.1:5503/public/Stage/sounds/pop.wav 404 (Not Found)

Right now the backend is running on localhost:5000, and the frontend is running on localhost:5503. The webpack version is 5.77.0.

I know webpack will automatically bundle assets if they are explicitly imported and referenced in files, but The problem is that the static javascript files are actually javascripts of Scratch codes that are converted using a packet called sb-edit, and I cannot change the way the code is written.

This is how the assets are referenced in the files:

new Costume("button4-a", "./Button4/costumes/button4-a.svg")

This is the content of the webpack.config, I am using asset-modules so there is no need for file-loader or any other loaders:


module.exports = {
    mode: 'development',
    entry: './index.js', 
    output: {
        filename: 'bundle.js', 
        path: path.resolve(__dirname, 'dist'),
        assetModuleFilename: '[path][name].[ext]',
    },
    experiments: { outputModule: true },
    externals: {
        'https://unpkg.com/leopard@^1/dist/index.esm.js': 'https://unpkg.com/leopard@^1/dist/index.esm.js',
    },
    externalsType: 'module',
    module: {
        rules: [
            {
                test: /\.(js)$/,
                exclude: /node_modules/,
                use: ['babel-loader']
            },
            {
                test: /\.(png|svg|jpg|jpeg|gif|mp3|wav)$/i,
                type: 'asset',
              },
          ],
    },
    optimization: {
        usedExports: true,
        sideEffects: false,
    },
    resolve: {
        fallback: {
          "path": require.resolve("path-browserify"),
          "url": require.resolve("url"),
          "events": require.resolve('events'),
        }
      },
};

This is one example (not the whole structure) of the static javascript files structure:

.
├── Sprite2/
│   ├── costumes/
│   │   └── costumes1.svg
│   ├── sounds/
│   │   └── pop.wav
│   └── Sprite2.js
├── Sprite3/
│   ├── costumes/
│   │   └── costumes1.svg
│   ├── sounds/
│   │   └── pop.wav
│   └── Sprite3.js
└── index.js

The file is referenced in the frontend like this:

<script type="module" src="http://localhost:5000/api/v1/scratch/bundle.js"></script>

I have tried changing the asset module types to asset/resource, asset/inline and asset but none of these options work. Is there any way to achieve this without making changes to the original code? Thank you so much in advance!"

英文:

I am using Webpack to pack static javascript files with folders and assets into a single output bundle.js file. The bundle.js file is then taken out from the original codebase and statically hosted in the backend server. The problem is that the assets are not bundled within the bundle.js file. When I try to display the publicly hosted index.js url in the frontent, I get the error message saying

GET http://127.0.0.1:5503/public/Stage/sounds/pop.wav 404 (Not Found)

Right now the backend is running on localhost:5000, and the frontend is running on localhost:5503. The webpack version is 5.77.0.

I know webpack will automatically bundle assets if they are explicitly imported and referenced in files, but The problem is that the static javascript files are actually javascripts of Scratch codes that are converted using a packet called sb-edit, and I cannot change the way the code is written.

This is how the assets are referenced in the files:

new Costume("button4-a", "./Button4/costumes/button4-a.svg")

This is the content of the webpack.config, I am using asset-modules so there is no need for file-loader or any other loaders:

const path = require('path')


module.exports = {
    mode: 'development',
    entry: './index.js', 
    output: {
        filename: 'bundle.js', 
        path: path.resolve(__dirname, 'dist'),
        assetModuleFilename: '[path][name].[ext]',
    },
    experiments: { outputModule: true },
    externals: {
        'https://unpkg.com/leopard@^1/dist/index.esm.js': 'https://unpkg.com/leopard@^1/dist/index.esm.js',
    },
    externalsType: 'module',
    module: {
        rules: [
            {
                test: /\.(js)$/,
                exclude: /node_modules/,
                use: ['babel-loader']
            },
            {
                test: /\.(png|svg|jpg|jpeg|gif|mp3|wav)$/i,
                type: 'asset',
              },
          ],
    },
    optimization: {
        usedExports: true,
        sideEffects: false,
    },
    resolve: {
        fallback: {
          "path": require.resolve("path-browserify"),
          "url": require.resolve("url"),
          "events": require.resolve('events'),
        }
      },
};

This is one example (not the whole structure) of the static javascript files structure:

.
├── Sprite2/
│   ├── costumes/
│   │   └── costumes1.svg
│   ├── sounds/
│   │   └── pop.wav
│   └── Sprite2.js
├── Sprite3/
│   ├── costumes/
│   │   └── costumes1.svg
│   ├── sounds/
│   │   └── pop.wav
│   └── Sprite3.js
└── index.js

The file is referenced in the frontend like this:

<script type="module" src="http://localhost:5000/api/v1/scratch/bundle.js"></script>

I have tried changing the asset module types to asset/resource, asset/inline and asset but none of these options work. Is there any way to achieve this without making changes to the original code? Thank you so much in advance!

答案1

得分: 0

我设法找到了一个解决办法,希望这对其他人有所帮助。

首先,我使用了 webpack 的 CopyWebpackPlugin 将所有资产复制到目标文件夹,同时保持它们的原始文件层次结构。我忽略了所有不是资产的文件:

plugins: [
  new CopyWebpackPlugin({
    patterns: [
      {
        from: './**/*',
        to: './',
        context: './',
        globOptions: {
          ignore: ['**/*.js', '**/node_modules/**', '**/*.html', '**/*.json']
        }
      }
    ]
  }),
],

然后,我将这些资产文件夹与生成的 bundle.js 文件一起放到后端静态保存的文件夹中。

最初,我只是在脚本标签中使用静态保存的 js 文件,如下所示:

<script type="module" src="http://localhost:5000/api/v1/scratch/bundle.js"></script>

现在,我首先使用 axios 获取 bundle js 文件,然后解析 js 文件,手动在 bundle 内部的相对资产路径前面添加后端的 URL:

axios.get('http://localhost:5000/url-to-statically-held-folder/bundle.js')
  .then(response => {
    let jsCode = response.data;

    jsCode = jsCode.replace(/\.[\/\w\s-]+\.(png|svg|jpg|jpeg|gif|mp3|wav)/g, (match) => {
      let urlStr = `http://localhost:5000/url-to-statically-held-folder/${match}`
      return urlStr;
    });

    const script = document.createElement('script');
    script.type = 'module';
    script.src = 'data:text/javascript;charset=utf-8,' + encodeURIComponent(jsCode);
    document.head.appendChild(script);
  })
  .catch(error => {
    console.error(error);
  });

现在它可以工作。

英文:

I managed to find a way to work around this, and I hope this will help others in some way.

First of all, I used the webpack's CopyWebpackPlugin to copy all the assets to the destination folder while maintaining their original file hierarchy. I ignored all the files that were not assets:

plugins: [
  new CopyWebpackPlugin({
    patterns: [
      {
        from: &#39;./**/*&#39;,
        to: &#39;./&#39;,
        context: &#39;./&#39;,
        globOptions: {
          ignore: [&#39;**/*.js&#39;, &#39;**/node_modules/**&#39;, &#39;**/*.html&#39;, &#39;**/*.json&#39;]
        }
      }
    ]
  }),
],

Then, I put these assets folder to the statically held folder in the backend along with the generated bundle.js file.

Originally I was only using the statically held js file in the script tag like this:

&lt;script type=&quot;module&quot; src=&quot;http://localhost:5000/api/v1/scratch/bundle.js&quot;&gt;&lt;/script&gt;

Now I am first using axios to get the bundle js file first, then I parse the js file and manually prepend the backend's URL in front of the relative assets paths inside the bundle:

axios.get(&#39;http://localhost:5000/url-to-statically-held-folder/bundle.js&#39;)
  .then(response =&gt; {
    let jsCode = response.data;

    jsCode = jsCode.replace(/\.[\/\w\s-]+\.(png|svg|jpg|jpeg|gif|mp3|wav)/g, (match) =&gt; {
      let urlStr = `http://localhost:5000/url-to-statically-held-folder/${match}`
      return urlStr;
    });

    const script = document.createElement(&#39;script&#39;);
    script.type = &#39;module&#39;;
    script.src = &#39;data:text/javascript;charset=utf-8,&#39; + encodeURIComponent(jsCode);
    document.head.appendChild(script);
  })
  .catch(error =&gt; {
    console.error(error);
  });

Now it works.

huangapple
  • 本文由 发表于 2023年4月11日 06:19:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75981152.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定