diff --git a/frappe.conf.js b/frappe.conf.js index 6e8c002f..1e591765 100644 --- a/frappe.conf.js +++ b/frappe.conf.js @@ -1,8 +1,10 @@ - +// frappe.conf.js template module.exports = { staticPath: './static', distPath: './dist', dev: { + entryHtml: 'index.html', + srcDir: 'src', outputDir: './dist', assetsPublicPath: '/', devServerPort: 8000, diff --git a/package.json b/package.json index 39f2e7ce..cd90e1ec 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "frappe-datatable": "^1.3.1", "friendly-errors-webpack-plugin": "^1.7.0", "html-webpack-plugin": "^3.2.0", - "imagemagick": "^0.1.3", "jquery": "^3.3.1", "jwt-simple": "^0.5.1", "luxon": "^1.0.0", @@ -48,8 +47,8 @@ "passport": "^0.4.0", "passport-jwt": "^4.0.0", "puppeteer": "^1.2.0", - "quickthumb": "^0.0.12", "sass-loader": "^7.0.3", + "sharp": "^0.20.8", "showdown": "^1.8.6", "socket.io": "^2.0.4", "sqlite3": "^3.1.13", diff --git a/server/index.js b/server/index.js index 3a925f7a..dfef1719 100644 --- a/server/index.js +++ b/server/index.js @@ -17,8 +17,8 @@ const { setupExpressRoute: setRouteForPDF } = require('frappejs/server/pdf'); const auth = require('./../auth/auth')(); const morgan = require('morgan'); const { addWebpackMiddleware } = require('../webpack/serve'); -const { getAppConfig } = require('../webpack/utils'); -const quickthumb = require('quickthumb') +const { getAppConfig, resolveAppDir } = require('../webpack/utils'); +const { thumbnailMiddleware } = require('./utils'); frappe.conf = getAppConfig(); @@ -42,7 +42,7 @@ module.exports = { app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(frappe.conf.distPath)); - app.use('/static', quickthumb.static(path.resolve(frappe.conf.staticPath), { type: 'resize' })); + app.use('/static', thumbnailMiddleware(resolveAppDir(frappe.conf.staticPath))); app.use(morgan('tiny')); diff --git a/server/utils.js b/server/utils.js index ec1d7f9a..bcf5d69a 100644 --- a/server/utils.js +++ b/server/utils.js @@ -1,7 +1,9 @@ const mkdirp = require('mkdirp'); const fs = require('fs'); -const getDirName = require('path').dirname; +const path = require('path'); +const getDirName = path.dirname; const os = require('os'); +const sharp = require('sharp'); module.exports = { writeFile(fullpath, contents) { @@ -17,10 +19,73 @@ module.exports = { }, readFile(filepath) { - return fs.readFileSync(filepath, 'utf-8'); + return fs.readFileSync(filepath, 'utf-8'); }, getTmpDir() { return os.tmpdir(); + }, + + thumbnailMiddleware(staticPath) { + + return function (req, res, next) { + + const filename = req.path.split(path.sep).slice(-1)[0] + const dimension = req.query.size || null + const staticFile = path.join(staticPath, filename) + + fs.exists(staticFile, (exists) => { + if (!exists) { + return next() + } + + fs.stat(staticFile, (err, stats) => { + if (err) { + throw err + } + + //Check if url is static file + if (stats.isFile()) { + + // Check if url has dimension parameters + if (dimension) { + let [width, height] = dimension.split('x'); + width = +width; + height = +height; + const thumbnailPath = path.join(staticPath, 'thumbnails'); + const destination = path.join(thumbnailPath, `${width}x${height}-${filename}`) + + // create thumbnails folder if not exists + if (!fs.existsSync(thumbnailPath)) { + fs.mkdirSync(thumbnailPath); + } + + // Check if thumbnail already present + fs.existsSync(destination, (exists) => { + if (exists) + return res.sendFile(destination) + }) + + // Resize image + sharp(staticFile) + .resize(width, height) + .toFile(destination) + .then(() => { + return res.sendFile(destination) + }) + .catch(err => { + console.error(err) + }) + + } else { + return res.sendFile(staticFile) + } + } else { + // File is not static + return next() + } + }) + }) + } } } \ No newline at end of file diff --git a/webpack/config.js b/webpack/config.js index 2d0247b3..6f1a7464 100644 --- a/webpack/config.js +++ b/webpack/config.js @@ -69,7 +69,7 @@ function getConfig() { alias: { 'vue$': 'vue/dist/vue.esm.js', 'deepmerge$': 'deepmerge/dist/umd.js', - '@': resolveAppDir(appConfig.dev.srcDir) + '@': appConfig.dev.srcDir ? resolveAppDir(appConfig.dev.srcDir) : null } }, plugins: [