英文:
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: './**/*',
to: './',
context: './',
globOptions: {
ignore: ['**/*.js', '**/node_modules/**', '**/*.html', '**/*.json']
}
}
]
}),
],
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:
<script type="module" src="http://localhost:5000/api/v1/scratch/bundle.js"></script>
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('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);
});
Now it works.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论