一个用于上传静态文件到 cdn 的 webpack 插件。
English | 中文
webpack-cdn-upload-plugin
可以帮助你使用 webpack 上传静态资源到 cdn 。你只需要提供一个上传函数即可。同时,它还能与html-webpack-plugin
, preload-webpack-plugin
, uglifyJsPlugin
, css-loader
, file-loader
等插件协同工作。
如果你正在使用 webpack 4, 请按照以下方式安装。
$ npm install webpack-cdn-upload-plugin --save-dev
如果你希望使用 webpack 3,请安装旧版本。
$ npm install webpack-cdn-upload-plugin@0 --save-dev
首先,你需要提供符合以下要求的上传函数。
async function upload(content: string, name: string, chunk?: Object): string | undefined {
// 在此处完成上传的工作,如果需要自定义 cdn 地址,则需要返回地址。
return url;
}
大多数情况下,我们可以使用 publicPath
来设定我们的 cdn 地址前缀。
{
entry: path.join(__dirname, 'index.js'),
output: {
path: OUTPUT_DIR,
filename: '[name].js',
chunkFilename: 'chunk-[name].js',
publicPath: 'http://cdn.toxicjohann.com/',
},
mode: 'development',
plugins: [
new HtmlWebpackPlugin(),
new WebpackCdnUploadPlugin({
upload(content, name) {
// 在此处完成上传的工作
},
}),
],
}
它会自动完成文件上传,并生成如下 html。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
</head>
<body>
<script type="text/javascript" src="http://cdn.toxicjohann.com/main.js"></script>
</body>
</html>
你可能会在 css 中引入如图片、字体等静态资源。他们通常会有 file-loader
进行处理,所以不会被视作一个 chunk 。
如果我们需要上传这些资源,需要打开 replaceUrlInCss
开关。
假设我们的 css 形如下方:
body {
background-image: url('./doggy.jpeg');
}
那么我们可以配置 webpack 如下:
{
entry: path.join(__dirname, 'index.js'),
output: {
path: OUTPUT_DIR,
filename: '[name].js',
chunkFilename: 'chunk-[name].js',
publicPath: 'http://cdn.toxicjohann.com/',
},
mode: 'development',
plugins: [
new HtmlWebpackPlugin(),
new WebpackCdnUploadPlugin({
upload(content, name) {
// 在此处完成上传的工作
},
replaceUrlInCss: true,
}),
],
}
它会上传该图片并生成 css 文件如下:
body {
background-image: url(http://cdn.toxicjohann.com/6fa90a9f47fd74fb99530864adbe95d4.jpeg);
}
而 html 文件如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
<link href="http://cdn.toxicjohann.com/main.css" rel="stylesheet"></head>
<body>
<script type="text/javascript" src="http://cdn.toxicjohann.com/main.js"></script>
</body>
</html>
我们也会通过 html 引入静态文件。这些文件我们一般会使用 html-loader
和 file-loader
进行处理。
如果你需要上传这些文件,你需要打开 replaceAssetsInHtml
开关。
假设我们的 html 模版如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<img src="./doggy.jpeg" />
</body>
</html>
我们配置 webpack 如下
{
entry: path.join(__dirname, 'fixtures', '/html/index.js'),
output: {
path: OUTPUT_DIR,
filename: '[name].js',
chunkFilename: '[name].js',
publicPath: 'http://cdn.toxicjohann.com/',
},
mode: 'prooduction',
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/,
use: [
{
loader: 'file-loader',
options: {},
},
],
},
{
test: /\.(html)$/,
use: {
loader: 'html-loader',
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'fixtures', '/html/index.html'),
}),
new WebpackCdnUploadPlugin({
upload(content, name) {
// 在此处完成上传的工作
},
replaceAssetsInHtml: true,
}),
new ExtractTextPlugin('[name].css'),
],
}
最终会生成如下 html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<img src="http://cdn.toxicjohann.com/6fa90a9f47fd74fb99530864adbe95d4.jpeg" />
<script type="text/javascript" src="http://cdn.toxicjohann.com/main.js"></script></body>
</html>
有几种情况你可能会需要自定义地址。比如你可能需要将不同文件上传到不同 cdn,又或者你的 cdn 不支持文件命名。
这种情况下,我们需要将新的地址通过上传函数返回,配置如下:
{
entry: path.join(__dirname, 'index.js'),
output: {
path: OUTPUT_DIR,
filename: '[name].js',
chunkFilename: 'chunk-[name].js',
publicPath: 'http://another-cdn.com',
},
mode: 'development',
plugins: [
new HtmlWebpackPlugin(),
new WebpackCdnUploadPlugin({
upload(content, name) {
// 进行上传工作并返回地址
return 'http://cdn.toxicjohann.com/' + name;
},
}),
],
}
最终生成结果如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
<link href="http://cdn.toxicjohann.com/main.css" rel="stylesheet"></head>
<body>
<script type="text/javascript" src="http://cdn.toxicjohann.com/main.js"></script>
</body>
</html>
你可能会发现,你的异步加载 bundle 并没有使用你自定义的 cdn 地址。这是因为异步加载的 bundle 需要通过修改原 javascript 文件来替换地址。
此时,你需要打开 renameAsyncChunkName
开关。
假设你引入了一个动态模块,并且需要定制 cdn 地址。
console.log('lol');
import('./module-a.js');
配置如下:
{
entry: {
file: path.join(__dirname, 'fixtures', 'file.js'),
},
output: {
path: OUTPUT_DIR,
filename: '[name].js',
},
mode: 'development',
plugins: [
new WebpackCdnUploadPlugin({
upload(content, name) {
return 'http://cdn.toxicjohann.com/' + name;
},
replaceAsyncChunkName: true,
}),
],
}
这样子,我们就能替换你的异步加载 bundle,最终他的执行效果如下。
<script type="text/javascript" charset="utf-8" src="http://cdn.toxicjohann.com/0.js"></script>
配置参数如下:
上传函数是用于将你的文件上传到 cdn,如果你需要自定义 cdn 地址,则在结果处返回你的 cdn 地址。
async function upload(content: string, name: string, chunk?: Object): string | undefined {
// do some upload job here
// if you need to customize the chunk link
// you need to return the new url.
return url;
}
你会接受到文件内容和文件名,如果该文件是一个 chunk, 你还会接受到 chunk 对象。
- 类型:
boolean
- 默认:
false
打开此开关,我们会将异步加载的 bundle 地址替换为你自定义的地址。
- 类型:
boolean
- 默认:
true
打开此开关,我们会检查 css 文件并将 url 中的 静态文件上传。
- 类型:
boolean
- 默认:
false
打开此地址,我们会检查 html 文件,并将 url 中的静态文件上传。
使用此方式时,请确保 html-webpack-plugin 置于 webpack-cdn-upload-plugin 前。