javascript - WebPack 创建 index.html 后 CSS 和 Bundle 的脚本路径有点偏离
问题描述
出于某种原因,webpack 正在尝试将client
我的 CSS 和 bundle 的脚本标签附加到 href。问题在于它是错误的。而且我不知道如何告诉它修剪那部分。
在迁移到 webpack 之前,这是我使用 Gulp 构建它时在生产环境中的样子:
请注意上面的一切是如何从客户端文件夹中植根的。你甚至看不到客户端文件夹,因为我认为 expressJS 说从那一点开始,所以你只能看到客户端中的根目录,例如lib、scripts等。
以下是我为静态资产提供服务的方式。我的ExpressJS服务器将静态评估的根文件夹设置为dist/client
. 即使我使用 Gulp 时也是如此:
.use(
express.static('dist/client', {
maxage: oneYear,
})
)
转发到现在:它现在正在使用我的新 webpack.config
这是来自 IDE 的dist的屏幕截图,因为它现在是使用 webpack 后的样子:
但是现在index.html是由 webpack 生成的:
<!doctype html><html lang="en"><head><title>My Title</title><meta charset="utf-8"><link href="https://ink.global.ssl.fastly.net/3.1.10/css/ink.min.css"><script src="https://ink.global.ssl.fastly.net/3.1.10/js/ink-all.min.js"></script><script src="https://ink.global.ssl.fastly.net/3.1.10/js/autoload.js"></script><link href="../client/lib/assets/css/main.c09764908684c2f56919.css?c09764908684c2f56919" rel="stylesheet"></head><body><div id="app"></div><script src="../client/scripts/app.c09764908684c2f56919.bundle.js?c09764908684c2f56919"></script></body></html>
webpack.config.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const isProduction = process.env.NODE_ENV === 'production';
const html = () => {
return new HtmlWebPackPlugin({
template: './src/client/index.html',
filename: './client/index.html',
hash: true,
});
};
const copyAllOtherDistFiles = () => {
return new CopyPlugin({
patterns: [
{ from: 'src/client/assets', to: 'client/lib/assets' },
{ from: 'src/server.js', to: './' },
{ from: 'src/api.js', to: './' },
{ from: 'package.json', to: './' },
{ from: 'ext', to: 'client/lib' },
{ from: 'feed.xml', to: 'client' },
{
from: 'src/shared',
to: './shared',
globOptions: {
ignore: ['**/*supressed.json'],
},
},
],
});
};
module.exports = {
entry: './src/client/index.js',
output: {
filename: 'client/scripts/app.[hash].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
target: 'web',
devServer: {
writeToDisk: true,
},
devtool: 'source-map',
optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true,
},
},
},
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
},
],
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ['url-loader'],
},
],
},
plugins: isProduction
? [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: isProduction
? 'client/lib/assets/css/main.[hash].css'
: 'main.css',
}),
html(),
copyAllOtherDistFiles(),
]
: [new CleanWebpackPlugin(), html(), copyAllOtherDistFiles()],
};
请注意,我的捆绑包生成的src包含../client/
和我的CSS脚本的href相同。
这样做的问题是我的应用程序是从dist 文件夹的根目录提供的。client
您会认为../client/
or ./client/
orclient/
会起作用,但事实并非如此。当我运行该站点时,我得到了这个,因为它找不到捆绑包:
正如您在下面看到的,它源于浏览器中的客户端文件夹上下文的所有内容:
(在迁移到 webpack 之后,这也很奇怪,如果我告诉 ExpressJS 已经从客户端文件夹开始,为什么我会看到客户端文件夹?当我使用 Gulp 使用相同的确切代码时,我没有看到客户端文件夹,因为我已经从浏览器的上下文中进入了它)
index.html
因此,当我在 dist 文件夹中手动更改生成的文件时,只是为了看看是否可以修复它,一切都解决得很好(注意我将其更改为 just lib/
and scripts/
):
</script><link href="lib/assets/css/main.c09764908684c2f56919.css?c09764908684c2f56919" rel="stylesheet"></head><body><div id="app"></div><script src="scripts/app.c09764908684c2f56919.bundle.js?c09764908684c2f56919"></script></body></html>
问题是我不知道如何让 webpack 在..client/
生成 index.html 时去掉 URL 的那一部分。 我已经尝试使用, or or来添加 publicPath 属性,但到目前为止没有运气。'/'
'./'
''
换句话说,这不会加载:http://localhost:8080/client/scripts/app.b4b3659d9f8b3681c26d.bundle.js
但这确实:
http://localhost:8080/scripts/app.b4b3659d9f8b3681c26d.bundle.js
http://localhost:8080/lib/assets/css/main.b4b3659d9f8b3681c26d.css
解决方案
我认为只要您将输出资产写入与服务器上设置的公用文件夹相同的文件夹,那么它就可以工作。假设client
仍然是公众:
.use(
express.static('dist/client', {
maxage: oneYear,
})
)
我建议在客户端的 webpack 配置中将整个输出设置为client
dir :publicPath
output: {
filename: 'scripts/app.[hash].bundle.js',
path: path.resolve(__dirname, 'dist/client'),
publicPath: '/'
}
使用上面的设置,我们不必指定 html 模板位置的文件夹:
new HtmlWebPackPlugin({
template: path.resolve(__dirname, 'src/client', 'index.html'),
filename: 'index.html',
hash: true,
});
推荐阅读
- python - AttributeError: 'list' 对象没有属性 'get' odoo
- android - 在主机 linux aarch64 上使用 gradle 构建 c++ 应用程序
- reactjs - 在我的 React 项目中运行“npm start”时出现模块错误
- docker - 运行容器错误时,Docker compose 从 docker-sync 配置迁移找不到 package.json
- php - 我在将车队购物车添加到我的 WordPress 网站时遇到问题
- windows - APPCOMMAND_LAUNCH_APP1 做什么?
- angular - 不能在 Angular 中结合静态元素和获取 ElementRef
- css - 如何隐藏 Angular 组件中的默认浏览器滚动条?
- python - 如何合并列表中的项目以避免项目内的重复内容?
- java - 在 Spring Boot 中启用 TLS 1.3 的问题