尽管我的开发服务器正在localhost:3000
上运行,但是我已经设置了主机文件以将www.mysite.com
指向本地主机。在我的JavaScript中,我有如下代码:
import myImage from '../assets/my-image.jpg'
const MyCmp => <img src={myImage} />
使用Webpack的file-loader
,它将导入的URL转换为托管图像的URL。但是,它使用该图像的localhost
路径,但是我希望它使用www.mysite.com
域。我查看了file-loader
的两个publicPath
and postTransformPublicPath
选项,但是这些选项似乎只允许您修改域 之后的部分路径。
答案 0 :(得分:1)
我个人不喜欢在构建输出中静态定义主机信息的概念。这是应该在运行时根据实际放置文件的位置来确定的。
如果您像我一样,那么这里有两个选择。 两者都涉及您调用已在即window / global范围内定义的全局方法。 全局方法的目的是在运行时解析根路径(域等)。
定义全局方法
因此,可以说您在启动代码中某处的全局范围内定义了一个方法,如下所示:
(<any>window).getWebpackBundleRootPath = function (webpackLibraryId) {
if (webpackLibraryId == null) return throw "OOOPS DO SOMETHING HERE!";
// Preferably these variables should be loaded from a config-file of sorts.
if(webpackLibraryId == "yourwebpacklibrary1") return "https://www.yoursite.com/";
// If you have other libraries that are hosted somewhere else, put them here...
return "...some default path for all other libraries...";
};
下一步是将webpack配置为在尝试解析路径时调用此全局方法。 正如我所提到的,有两种方法,一种用于操纵Webpack的输出,另一种则更多地集成在Webpacks配置中(尽管仅适用于文件加载器,但我认为它就足够了)。
值得一提的是,如果只有一个捆绑软件或将所有捆绑软件托管在一个地方,则不需要全局方法。那么使用一个全局变量就足够了。修改下面的示例以适应这一点应该很容易。
此解决方案在构建后不需要执行任何操作。如果这适合您的需求并涵盖所有情况,那么我会选择此选项。
编辑您的Webpack配置文件
var path = require('path');
let config = {
entry: {
'index': path.join(__dirname, '/public/index.js')
},
output: {
path: path.join(__dirname, '/dist/'),
filename: 'index-bundle.js',
publicPath: 'https://localhost:3000/',
library: 'yourwebpacklibrary1',
...
},
module: {
rules: [{
// Please note that this only defines the resolve behavior for ttf. If you want to resolve other files you need to configure the postTransformPublicPath for those too. This is a big caveat in my opinion and might be a reason for using second option.
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: [{
loader: 'file-loader',
options: {
outputPath: 'assets/fonts', // The folder where you store your fonts.
name: '[name].[ext]',
// This is where the magic happens. This lets you override the output of webpack file resolves.
postTransformPublicPath: function (p) {
// Because of the way webpack file-loader works the input from to this method will look something like this: __webpack_public_path__ + "/assets/fonts/yourfont.ttf"
// But we are not interested in using the __webpack_public_path__ variable so lets remove that.
p = p.replace('__webpack_public_path__ + ', '');
// Return a stringified call to our global method and append the relative path to the root path returned.
return `getWebpackBundleRootPath("${config.output.library}") + ${p}`;
}
}
}]
},
},
...
};
module.exports = config;
您可能已经在webpack配置文件的注释中注意到了,您需要为添加的每个文件加载器指定解析行为(如果有人知道更好的方法,请告诉我)。这就是为什么我仍然使用第二个选项的原因。
示例webpack.config.js文件
为完整起见,这里是一个webpack.config.js文件的示例,其中包含在postbuild脚本中使用的变量。
var path = require('path');
module.exports = {
entry: {
'index': path.join(__dirname, '/public/index.js')
},
output: {
path: path.join(__dirname, '/dist/'),
filename: 'index-bundle.js',
publicPath: 'https://localhost:3000/',
library: 'yourwebpacklibrary1',
...
},
...
}
创建一个postbuild.js文件
在package.json旁边创建具有以下内容的文件postbuild.js:
const fs = require('fs');
// We take the path to the webpack config file as input so that we can read settings from it.
const webpackConfigFile = process.argv[2];
// Read the webpack config file into memory.
const config = require(webpackConfigFile);
// The file to manipulate is the output javascript bundle that webpack produces.
const inputFile = config.output.path + config.output.filename;
// Load the file into memory.
let fileContent = fs.readFileSync(inputFile, 'utf8');
// Replace the default public path with the call to the method. Please note that if you specify a publicPath as '/' or something very common you might end up with a problem so make sure it is unique in the file to avoid other unrelated stuff being replaced as well.
fileContent = fileContent.replace('"' + config.output.publicPath + '"', 'getWebpackBundleRootPath("' + config.output.library + '")');
// Save the manipulated file back to disk.
fs.writeFileSync(inputFile, fileContent, 'utf8');
在构建时自动调用postbuild.js
下一步是在每次构建后实际调用postbuild.js脚本。 可以在package.json的post script 中完成,就像这样(在package.json的script部分):
{
"scripts": {
"build": "webpack",
"postbuild": "node postbuild.js ./webpack.config.js"
}
}
从现在开始,无论何时运行构建脚本,它还将运行后构建脚本(从npm或yarn等)。
当然,您也可以在每次构建后手动手动运行postbuild.js脚本。
答案 1 :(得分:0)
但这些内容似乎仅允许您修改路径后面的域部分。
并非如此,您可以给它提供一个包含域的URL。
以您为例,假设您的图片位于assets
目录下,则webpack.config.js
中将有类似的内容
...
module: {
rules: [
...
{
test: /\.(png|jpe?g|gif|svg)$/,
use: {
loader: 'file-loader',
options: {
publicPath: 'https://www.example.com/assets',
outputPath: 'assets'
}
}
},
...
]
}
...