Изображения GET генерируют ошибку 404 при работе с использованием Webpack и AngularJS
У меня есть эта загадка, которую я не могу решить после многих испытаний:
Я не могу загрузить статические изображения в производство;
все хорошо во время разработки (npm run serve), даже при обслуживании файлов из dist (npm run serve: dist)
Версии
Webpack: 3.12.0
файл-загрузчик: 1.1.11
url-загрузчик: 1.1.2
AngularJS: 1.6,9
При разработке:
Мой index.html содержит эту строку, и веб-пакет не будет загружаться без
<base href="/"></base>
в то время как мой блок конфигурации AngularJS содержит
$locationProvider.hashPrefix('');
Я использую URL-адрес, такой как http://localhost:3000/#/appName/listComponent/users
и я могу видеть каждое изображение с помощью ng-src (иногда оно динамически связывается), как это
<img ng-src="app/images/image1.png">
структура папок такая
ui/
├── conf/
│ ├── browsersync-dist.conf.js
│ ├── browsersync.conf.js
│ ├── gulp.conf.js
│ ├── webpack-dist.conf.js
│ └── webpack.conf.js
├── gulp_tasks/
│ ├── browsersync.js
│ ├── misc.js
│ └── webpack.js
├── node_modules/
├── src/
│ ├── app/
│ │ ├── config.js //global variables
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── index.less
│ │ ├── images/ <--
│ │ ├── actual_app_folders/
│ │ └── ...
├── gulpfile.js
└── package.json
В моем webpack-dist.js у меня есть следующее
module.exports = {
module: {
loaders: [
{
test: /\.json$/,
loaders: [
'json-loader'
]
},
{
test: /\.js$/,
exclude: [
/node_modules/
],
loader: 'babel-loader',
options: {
presets: ['es2015']
}
},
{
test: /\.js$/,
exclude: [
/node_modules/
],
loaders: [
'eslint-loader'
],
enforce: 'pre'
},
{
test: /\.(css|less)$/,
exclude: '/node_modules/roboto-fontface/',
loaders: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader?minimize!less-loader!postcss-loader'
})
},
{
test: /\.html$/,
loaders: [
'html-loader'
]
},
{
test: /\.(jpe?g|png|gif|svg|eot|woff|ttf|svg|woff2)$/,
loader: 'url-loader?name=[name].[ext]'
}
]
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
FailPlugin,
new HtmlWebpackPlugin({
template: conf.path.src('/app/index.html'),
inject: true,
chunksSortMode: 'dependency'
}),
new webpack.optimize.CommonsChunkPlugin({
name: ['vendors', 'config'],
minChunks: Infinity
}),
new ExtractTextPlugin('index-[contenthash].css'),
new webpack.LoaderOptionsPlugin({
options: {
postcss: () => [autoprefixer]
}
})
],
output: {
path: conf.paths.dist,
filename: function(output) {
return output['chunk']['name'] === 'config' ? '[name].js' : '[name]-[hash].js';
},
chunkFilename: '[name]-[hash].js'
},
entry: {
app: `./${conf.path.src('/app/index')}`,
config: `./${conf.path.src('/app/config')}`,
vendors: Object.keys(pkg.dependencies).concat(['webpack-material-design-icons'])
}
};
В ПРОИЗВОДСТВЕ
Процесс сборки добавляет /customer_company_name/our_company_name/
префикс к пути, который становится
http://<customer_domain>:<domain_port>/customer_company_name/our_company_name/#/appName/listingComponent/users
в то время как структура папок такая
our_company_name/
├── app/
│ ├── images/ <--
│ │ ├── image1.png
│ │ └── image2.png
├── app-<random_number>.js
├── config.js
├── favicon.ico
├── index.html
├── index-<random_number>.css
└── vendors.js
ЭТА ПРОБЛЕМА
Теперь каждый раз, когда нужно показать картинку, браузер получает ошибку 404, как это
GET http://<customer_domain>:<domain_port>/app/images/image1.png 404 (Not Found)
пока запрос должен быть сделан вот так
GET http://<customer_domain>:<domain_port>/customer_company_name/our_company_name/index.js
как и любой другой файл в приложении.
Что я пробовал
Пока ничего из следующего не помогло:
- Изменить базовый тег при сборке в следующем
<base href="/customer_company_name/our_company_name/"></base>
(это в настоящее время сохраняется) - Явно требуются картинки вместе с любым другим файлом в index.js
require('./images/ODM_trasp48px.png');
(это в настоящее время сохраняется) - Использование publicPath в веб-пакете
output.publicPath: '/customer_company_name/our_company_name/'
а такжеoutput.publicPath: '/'
- Использование загрузчика файлов вместо url-загрузчика (в настоящее время сохраняется)
- Использование загрузчика файлов с
options: { useRelativePath: true }
- Использование загрузчика файлов с
options: { publicPath: /customer_company_name/our_company_name/ }
Можете ли вы помочь мне, ребята, пожалуйста?
4 ответа
РЕШЕНИЕ Начнем с
output.publicPath: '/customer_company_name/our_company_name/'
это позаботится о правильном переписывании путей ng-/src, как описано здесь.
Нам не понадобится html-loader
для разбора ng-/src нужно только всегда использовать ng-src, иначе сборка не будет успешной.
В конце концов, нет необходимости <base>
тег и ни начальная косая черта в каждом пути используется для ссылки на изображения.
Я буду обновлять этот ответ по мере улучшения webpack-dist.conf.js
/ весь проект в лучшую сторону.
Никакой ответ не сработал сам по себе, поэтому я попробую их комбинации, так как некоторые предложения выглядят законными.
В конце концов, если я не смогу решить эту проблему, я попытаюсь отбросить префикс рабочего пути /customer_company_name/our_company_name/
,
Я думаю, что проблема не в шаблоне замены, так как он работает для других типов файлов, а в том, что webpack не знает, что делать с атрибутом ng-src. Я думаю, что он только смотрит на атрибут src img по умолчанию. Вы можете изменить его так, чтобы он распознал ng-src как:
module.exports = {
module: {
loaders: [
...
{
test: /\.html$/,
loaders: [ "html-loader?" + JSON.stringify({ attrs: ["img:src", "img:ng-src"] })]
},
...
],
...
Синтаксис alt:
{
test: /\.html$/,
loaders: [ "html-loader?attrs=img:src img:ng-src" ]
}
Перед изменением вашей конфигурации вы можете просто проверить, является ли это причиной, проверив, работает ли замена в настоящее время правильно для тегов img с простой статической .
Можете ли вы попробовать ниже изменить в ваш index.html
<base href="./"></base>
Вместо того, чтобы разрешать webpack разбирать ваши шаблоны, вы можете попытаться явно импортировать ваши изображения и передать их в ваш шаблон.
Импортированные изображения будут обработаны настроенным image-loader
или же url-loader
,
Статическое изображение
const myImage = require('./path/to/images/image1.png');
// In component declaration
`<img ng-src="${myImage}">`
Динамическое изображение
Использование веб-пакета require.context
const pathToImages = require.context('./path/to/images', true);
const dynamicImageName = 'foo.jpg',
// In component declaration
`<img ng-src="${pathToImages(dynamicImageName, true)}">`