在开发小程序的时候由于包的大小受限,导致很多公司购买oss,cdn,单独弄台服务器上传静态资源,
但是前端自己一张一张上传实在显得太笨拙,还是开发自动化的脚本来的舒服,最重要的原因是维护
旧代码,导致自己没法完全找到所有的图片相关代码实在坑爹,所以想办法一次性解决。
这里的方法适用小程序第三方框架,mpvue,taro,uni-app等webpack构建的框架
web当然也是支持的
思路
一开始想到的办法就是项目打包完毕后将图片文件夹内的图片全部上传,配置url-loader将图片路径全部替换成网络路径,途中遇到很多坑,待我一一道来。
步骤
1.首先到webpack官网找到打包完毕的钩子,让后在钩子里做点事
- 相关钩子文档 webpack钩子
- 我这里使用的是(afterEmit):生成资源到 output 目录之后。
— 直接上代码
class OssPlugin {
apply(compiler) {
compiler.hooks.afterEmit.tapAsync('done', (compilation, callback) => {
// 此处通过node api读取打包文件列表
fs.readdir('build/images', (err, files) => {
if (err) {
console.error(err)
} else {
uploadImg(files)
}
})
// 记得调用callback避免webpack后续动作不执行
callback()
})
复制代码
2.编写图片上传函数,此处demo为阿里云oss
async function uploadImg(files) {
let OSS = require('ali-oss')
let client = new OSS({
region: 'oss-cn-shenzhen', // cdn节点位置
accessKeyId: '',
accessKeySecret: '',
bucket: '', // oss bucket目录
});
// 此处为循环上传,用for循环相信各位大佬都了解(避免并行上传出错)
// 同时方便统计是否上传完毕
for (let i = 0, len = files.length; i < len; i++) {
// common/${files[i]}为上传后路径,阿里云支持指定上传后文件名
// 指定文件名是必须的,因为生成的网络路径是拼接好的,不知道其他平台支不支持,这一步尤为关键,不支持就做不了下一步
await client.put(`common/${files[i]}`, `build/images/${files[i]}`);
}
// 图片上传完毕后删除图片
for (let i = 0, len = files.length; i < len; i++) {
fs.unlinkSync(`dist/common/${files[i]}`)
}
console.log('\x1B[44m%s\x1B[49m', 'upload img fished>>>>>>>>>>>>>>>')
}
复制代码
是不是很简单的就完成了一个webpack插件,是不是也能成为webpack大佬了
2.最重要的步骤来了,配置图片路径
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve('url-loader'),
options: {
// 正式环境一律不使用base64,全部打包为文件
limit: isEnvProduction ? imageInlineSizeLimit : 0,
// 此处两个配置尤为重要,路径会拼接为:http://movie.xmwhs88.com/images/[name].[hash:8].[ext]
// images一定要和上传后生成的路径一至
name: 'images/[name].[hash:8].[ext]',
// publicPath记得加上http:(https:)避免转换成绝对路径
publicPath: isEnvDevelopment ? '' : 'http://movie.xmwhs88.com/'
},
},
复制代码
如果你也有需要和我一样部分图片不需要上传,请写两个url-loader配置,test正则单独匹配,不上传的文件目录单独制定(就是前面的images换一个,避免被删) 文件名统一规范
3,最后别忘了在webpack,plugin里面加上你的插件
后记
是不是超级简单,如果你有ftp上传的需求,参考以下代码
// 此处使用sftp,ftp请自行谷歌
const Sftp = require('node-ssh');
const ftpConfig = {
host: '',
port: '22',
username: '',
password: ''
}
function uploadImg() {
return new Promise((resolve, reject) => {
let ssh = new Sftp()
ssh.connect(ftpConfig).then(() => {
// 支持上传文件夹
ssh.putDirectory(/* 本地 */'build/images', /* 远程 */'public/images').then(() => {
resolve()
// 上传完毕之后记得关闭,避免进程一直存在需要手动关闭
ssh.dispose()
}).catch(err => {
reject(err)
ssh.dispose()
})
}).catch(err => {
reject(err)
ssh.dispose()
})
})
}
复制代码
配置关键点在于上传时机和图片路径 觉得可以请给我666 基于create-react-app脚手架改造的项目地址:webpack-cdn-img