Skip to content

Commit

Permalink
Merge pull request #21 from studiokloek/fix-static-files
Browse files Browse the repository at this point in the history
Make sure static file are also processed
  • Loading branch information
anncwb authored Jan 24, 2022
2 parents c797592 + 0573b9d commit 464f271
Show file tree
Hide file tree
Showing 7 changed files with 467 additions and 34 deletions.
Binary file added example/public/images/static-test.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/public/images/static-test.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/public/images/static-test.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
340 changes: 340 additions & 0 deletions example/public/images/static-test.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 16 additions & 4 deletions example/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
<template>
<div>
<img :src="gif" />
<img :src="jpg" />
<img :src="png" />
<img :src="svg" />
<h1>Example</h1>
<div>
<h2>Generated</h2>
<img :src="gif" />
<img :src="jpg" />
<img :src="png" />
<img :src="svg" />
</div>
<div>
<h2>static</h2>
<img src="/images/static-test.gif" />
<img src="/images/static-test.jpg" />
<img src="/images/static-test.png" />
<img src="/images/static-test.svg" />
</div>
</div>
</template>

Expand All @@ -14,6 +25,7 @@
import jpg from './assets/test.jpg';
import png from './assets/test.png';
import svg from './assets/test.svg';
export default defineComponent({
name: 'App',
components: {},
Expand Down
104 changes: 74 additions & 30 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Plugin, ResolvedConfig } from 'vite';
import type { VitePluginImageMin } from './types';
import path from 'path';
import { normalizePath } from 'vite';
import { isNotFalse, isBoolean, isRegExp, isFunction } from './utils';
import fs from 'fs-extra';
import { isNotFalse, isBoolean, isRegExp, isFunction, readAllFiles } from './utils';
import chalk from 'chalk';
import { debug as Debug } from 'debug';

Expand All @@ -21,6 +21,7 @@ const extRE = /\.(png|jpeg|gif|jpg|bmp|svg)$/i;

const exportFn = (options: VitePluginImageMin = {}): Plugin => {
let outputPath: string;
let publicDir: string;
let config: ResolvedConfig;

const emptyPlugin: Plugin = {
Expand All @@ -34,15 +35,46 @@ const exportFn = (options: VitePluginImageMin = {}): Plugin => {
}

debug('plugin options:', options);

const mtimeCache = new Map<string, number>();
let tinyMap = new Map<string, { size: number; oldSize: number; ratio: number }>();

async function processFile(filePath: string, buffer: Buffer) {
let content:Buffer;

try {
content = await imagemin.buffer(buffer, {
plugins: getImageminPlugins(options),
});

const size = content.byteLength,
oldSize = buffer.byteLength;

tinyMap.set(filePath, {
size: size / 1024,
oldSize: oldSize / 1024,
ratio: size / oldSize - 1,
});

return content;
} catch (error) {
config.logger.error('imagemin error:' + filePath);
}
}

return {
...emptyPlugin,
apply: 'build',
enforce: 'post',
configResolved(resolvedConfig) {
configResolved(resolvedConfig) {
config = resolvedConfig;
outputPath = path.join(config.root, config.build.outDir);
outputPath = config.build.outDir;

// get public static assets directory: https://vitejs.dev/guide/assets.html#the-public-directory
if (typeof config.publicDir === 'string') {
publicDir = config.publicDir;
}

debug('resolvedConfig:', resolvedConfig);
},
async generateBundle(_options, bundler) {
Expand All @@ -60,33 +92,48 @@ const exportFn = (options: VitePluginImageMin = {}): Plugin => {
}

const handles = files.map(async (filePath: string) => {
let source = (bundler[filePath] as any).source;

const fullFilePath = path.resolve(outputPath, filePath);
let content: Buffer | null = null;
try {
content = await imagemin.buffer(source, {
plugins: getImageminPlugins(options),
});
} catch (error) {
console.log(error);
config.logger.error('imagemin error:' + fullFilePath);
}
const oldSize = source.length;
const size = content?.byteLength ?? 0;
tinyMap.set(fullFilePath, {
size: size / 1024,
oldSize: oldSize / 1024,
ratio: size / oldSize - 1,
});
let source = (bundler[filePath] as any).source;
const content = await processFile(filePath, source);
if (content) {
(bundler[filePath] as any).source = content;
}
});

await Promise.all(handles);
},
closeBundle() {
async closeBundle() {
if (publicDir) {
const files:string[] = [];

// try to find any static images in original static folder
readAllFiles(publicDir).forEach((file) => {
filterFile(file, filter) && files.push(file);
});

if (files.length) {
const handles = files.map(async (publicFilePath: string) => {
// now convert the path to the output folder
const filePath = publicFilePath.replace(publicDir + '/', '');
const fullFilePath = path.join(outputPath, filePath);

const { mtimeMs } = await fs.stat(fullFilePath);
if (mtimeMs <= (mtimeCache.get(filePath) || 0)) {
return;
}

const buffer = await fs.readFile(fullFilePath);
const content = await processFile(filePath, buffer);

if (content) {
await fs.writeFile(fullFilePath, content);
mtimeCache.set(filePath, Date.now());
}
});

await Promise.all(handles);
}
}

if (verbose) {
handleOutputLogger(config, tinyMap);
}
Expand Down Expand Up @@ -114,10 +161,6 @@ function handleOutputLogger(
recordMap.forEach((value, name) => {
let { ratio, size, oldSize } = value;

const rName = normalizePath(name).replace(
normalizePath(`${config.root}/${config.build.outDir}/`),
''
);
ratio = Math.floor(100 * ratio);
const fr = `${ratio}`;

Expand All @@ -126,8 +169,8 @@ function handleOutputLogger(
const sizeStr = `${oldSize.toFixed(2)}kb / tiny: ${size.toFixed(2)}kb`;

config.logger.info(
chalk.dim(path.basename(config.build.outDir) + '/') +
chalk.blueBright(rName) +
chalk.dim(path.basename(config.build.outDir)) + '/' +
chalk.blueBright(name) +
' '.repeat(2 + maxKeyLength - name.length) +
chalk.gray(`${denseRatio} ${' '.repeat(valueKeyLength - fr.length)}`) +
' ' +
Expand All @@ -137,6 +180,7 @@ function handleOutputLogger(
config.logger.info('\n');
}


function filterFile(file: string, filter: RegExp | ((file: string) => boolean)) {
if (filter) {
const isRe = isRegExp(filter);
Expand Down
37 changes: 37 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import fs from 'fs';
import path from 'path';

export const isFunction = (arg: unknown): arg is (...args: any[]) => any =>
typeof arg === 'function';

Expand All @@ -15,3 +18,37 @@ export const isNotFalse = (arg: unknown): arg is boolean => {

export const isRegExp = (arg: unknown): arg is RegExp =>
Object.prototype.toString.call(arg) === '[object RegExp]';


/*
* Read all files in the specified folder, filter through regular rules, and return file path array
* @param root Specify the folder path
* [@param] reg Regular expression for filtering files, optional parameters
* Note: It can also be deformed to check whether the file path conforms to regular rules. The path can be a folder or a file. The path that does not exist is also fault-tolerant.
*/
export function readAllFiles(root: string, reg?: RegExp) {
let resultArr: string[] = [];
try {
if (fs.existsSync(root)) {
const stat = fs.lstatSync(root);
if (stat.isDirectory()) {
// dir
const files = fs.readdirSync(root);
files.forEach(function (file) {
const t = readAllFiles(path.join(root, '/', file), reg);
resultArr = resultArr.concat(t);
});
} else {
if (reg !== undefined) {
if (isFunction(reg.test) && reg.test(root)) {
resultArr.push(root);
}
} else {
resultArr.push(root);
}
}
}
} catch (error) {}

return resultArr;
}

0 comments on commit 464f271

Please sign in to comment.