mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2025-12-06 02:30:47 -08:00
refactor: fix path and webpack
This commit is contained in:
parent
1808972197
commit
92edc7b528
15 changed files with 1692 additions and 322 deletions
1791
package-lock.json
generated
1791
package-lock.json
generated
File diff suppressed because it is too large
Load diff
14
package.json
14
package.json
|
|
@ -10,7 +10,7 @@
|
|||
"lint": "eslint ./src --ext js",
|
||||
"lint:fix": "eslint ./src --ext js --fix",
|
||||
"installType": "typesync",
|
||||
"postinstall": "npx electron-builder install-app-deps && if-env CI=true && echo \"skip flow-typed\" || npm run installType"
|
||||
"postinstall": "npx electron-builder install-app-deps && if-env CI=true && echo \"skip typesync\" || npm run installType"
|
||||
},
|
||||
"repository": "https://github.com/tiddly-gittly/TiddlyGit-Desktop",
|
||||
"author": "Lin Onetwo<linonetwo012@gmail.com>, Quang Lam <quang.lam2807@gmail.com>",
|
||||
|
|
@ -59,6 +59,14 @@
|
|||
"js": "./src/services/preload/main.ts"
|
||||
},
|
||||
"name": "main_window"
|
||||
},
|
||||
{
|
||||
"html": "./src/index.html",
|
||||
"js": "./src/index.tsx",
|
||||
"preload": {
|
||||
"js": "./src/services/preload/view.ts"
|
||||
},
|
||||
"name": "web_view"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -68,7 +76,6 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@cliqz/adblocker-electron": "1.18.3",
|
||||
"@tiddlygit/tiddlywiki": "^5.1.23-prerelease.20201217",
|
||||
"bluebird": "^3.7.2",
|
||||
"chokidar": "^3.4.2",
|
||||
|
|
@ -149,6 +156,7 @@
|
|||
"concurrently": "5.3.0",
|
||||
"cross-env": "7.0.2",
|
||||
"csp-html-webpack-plugin": "4.0.0",
|
||||
"css-loader": "^5.0.1",
|
||||
"date-fns": "2.16.1",
|
||||
"electron": "^12.0.0-beta.10",
|
||||
"electron-builder": "22.8.1",
|
||||
|
|
@ -170,6 +178,7 @@
|
|||
"fork-ts-checker-webpack-plugin": "^6.0.7",
|
||||
"graphql-hooks": "^5.0.0",
|
||||
"if-env": "^1.0.4",
|
||||
"image-webpack-loader": "^7.0.1",
|
||||
"node-loader": "^1.0.2",
|
||||
"prettier": "^2.2.1",
|
||||
"prop-types": "15.7.2",
|
||||
|
|
@ -188,6 +197,7 @@
|
|||
"rimraf": "^3.0.2",
|
||||
"simplebar": "6.0.0-beta.4",
|
||||
"simplebar-react": "3.0.0-beta.5",
|
||||
"style-loader": "^2.0.0",
|
||||
"styled-components": "5.2.0",
|
||||
"styled-is": "1.3.0",
|
||||
"subscriptions-transport-ws": "^0.9.18",
|
||||
|
|
|
|||
|
|
@ -4,18 +4,21 @@ import os from 'os';
|
|||
|
||||
const isMac = process.platform === 'darwin';
|
||||
|
||||
const sourcePath = path.resolve(__dirname, '..', '..');
|
||||
|
||||
// FIXME: change to electron forge path
|
||||
const REACT_PATH = isDev ? 'http://localhost:3000' : `file://${path.resolve(__dirname, '..', '..', 'build', 'index.html')}`;
|
||||
// .app/Contents/Resources/wiki/
|
||||
const TIDDLYWIKI_TEMPLATE_FOLDER_PATH = isDev ? path.resolve(__dirname, '..', '..', 'template', 'wiki') : path.resolve(process.resourcesPath, '..', 'wiki');
|
||||
const TIDDLYWIKI_TEMPLATE_FOLDER_PATH = isDev ? path.resolve(sourcePath, '..', 'template', 'wiki') : path.resolve(process.resourcesPath, '..', 'wiki');
|
||||
const TIDDLERS_PATH = 'tiddlers';
|
||||
const ICON_PATH = isDev ? path.resolve(__dirname, '..', 'icon.png') : `file://${path.resolve(__dirname, '..', 'icon.png')}`;
|
||||
const ICON_PATH = isDev ? path.resolve(sourcePath, 'icon.png') : `file://${path.resolve(__dirname, '..', 'icon.png')}`;
|
||||
const CHROME_ERROR_PATH = 'chrome-error://chromewebdata/';
|
||||
const DESKTOP_PATH = path.join(os.homedir(), 'Desktop');
|
||||
const LOG_FOLDER = isDev
|
||||
? path.resolve(__dirname, '..', '..', 'logs')
|
||||
? path.resolve(sourcePath, '..', 'logs')
|
||||
: isMac
|
||||
? path.resolve(process.resourcesPath, '..', 'logs')
|
||||
: path.resolve(os.homedir(), '.tg-note', 'logs');
|
||||
const LOCALIZATION_FOLDER = isDev ? path.resolve(__dirname, '..', '..', 'localization') : path.resolve(process.resourcesPath, '..', 'localization');
|
||||
const LOCALIZATION_FOLDER = isDev ? path.resolve(sourcePath, '..', 'localization') : path.resolve(process.resourcesPath, '..', 'localization');
|
||||
|
||||
export { REACT_PATH, TIDDLYWIKI_TEMPLATE_FOLDER_PATH, TIDDLERS_PATH, ICON_PATH, CHROME_ERROR_PATH, DESKTOP_PATH, LOG_FOLDER, LOCALIZATION_FOLDER, isDev };
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ipcMain, nativeTheme, protocol, session, powerMonitor, remote } from 'electron';
|
||||
import { ipcMain, nativeTheme, protocol, session, powerMonitor, app } from 'electron';
|
||||
import isDev from 'electron-is-dev';
|
||||
import fs from 'fs';
|
||||
// @ts-expect-error ts-migrate(2529) FIXME: Duplicate identifier 'Promise'. Compiler reserves ... Remove this comment to see the full error message
|
||||
|
|
@ -27,11 +27,6 @@ import MAILTO_URLS from './constants/mailto-urls';
|
|||
|
||||
import './libs/updater';
|
||||
|
||||
// eslint-disable-next-line import/order, global-require
|
||||
const app = require('electron').app || remote.app;
|
||||
// see https://github.com/electron/electron/issues/18397
|
||||
app.allowRendererProcessReuse = true;
|
||||
|
||||
const gotTheLock = app.requestSingleInstanceLock();
|
||||
|
||||
declare global {
|
||||
|
|
@ -50,7 +45,7 @@ declare global {
|
|||
app.on('second-instance', () => {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
const win = mainWindow.get();
|
||||
if (win != undefined) {
|
||||
if (win !== undefined) {
|
||||
if (win.isMinimized()) win.restore();
|
||||
win.focus();
|
||||
}
|
||||
|
|
@ -102,9 +97,9 @@ if (!gotTheLock) {
|
|||
|
||||
loadListeners();
|
||||
|
||||
const commonInit = () => {
|
||||
const commonInit = async (): Promise<void> => {
|
||||
// eslint-disable-next-line promise/catch-or-return
|
||||
app
|
||||
return await app
|
||||
.whenReady()
|
||||
.then(
|
||||
() =>
|
||||
|
|
@ -114,7 +109,7 @@ if (!gotTheLock) {
|
|||
callback(pathname);
|
||||
}),
|
||||
)
|
||||
.then(() => mainWindow.createAsync())
|
||||
.then(async () => await mainWindow.createAsync())
|
||||
.then(() => {
|
||||
const { hibernateUnusedWorkspacesAtLaunch, proxyBypassRules, proxyPacScript, proxyRules, proxyType, themeSource } = getPreferences();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
import fetch from 'node-fetch';
|
||||
import ProxyAgent from 'proxy-agent';
|
||||
|
||||
// somehow, ELECTRON_RUN_AS_NODE is set to '1' instead of 'true' as specified
|
||||
// so use generic process.env.ELECTRON_RUN_AS_NODE condition instead of
|
||||
// something like process.env.ELECTRON_RUN_AS_NODE === 'true'
|
||||
const { getPreference }: any = process.env.ELECTRON_RUN_AS_NODE ? {} : require('./preferences');
|
||||
|
||||
// @ts-expect-error ts-migrate(7019) FIXME: Rest parameter 'arguments_' implicitly has an 'any... Remove this comment to see the full error message
|
||||
const customizedFetch = (url: any, _options: any, ...arguments_) => {
|
||||
let proxyPacScript = process.env.PROXY_PAC_SCRIPT;
|
||||
let proxyRules = process.env.PROXY_RULES;
|
||||
let proxyType = process.env.PROXY_TYPE;
|
||||
if (getPreference) {
|
||||
proxyPacScript = getPreference('proxyPacScript');
|
||||
proxyRules = getPreference('proxyRules');
|
||||
proxyType = getPreference('proxyType');
|
||||
}
|
||||
|
||||
const options = { ..._options };
|
||||
if (proxyType === 'rules') {
|
||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string | undefined' is not assig... Remove this comment to see the full error message
|
||||
const agent = new ProxyAgent(proxyRules);
|
||||
options.agent = agent;
|
||||
} else if (proxyType === 'pacScript') {
|
||||
const agent = new ProxyAgent(`pac+${proxyPacScript}`);
|
||||
options.agent = agent;
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(2556) FIXME: Expected 1-2 arguments, but got 3 or more.
|
||||
return fetch(url, options, ...arguments_);
|
||||
};
|
||||
|
||||
export default customizedFetch;
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import winston from 'winston';
|
||||
import { LOG_FOLDER } from '../../constants/paths';
|
||||
import RendererTransport from './renderer-transport';
|
||||
require('winston-daily-rotate-file');
|
||||
import 'winston-daily-rotate-file';
|
||||
|
||||
const logger = winston.createLogger({
|
||||
levels: {
|
||||
emerg: 0,
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ import semver from 'semver';
|
|||
import settings from 'electron-settings';
|
||||
|
||||
import sendToAllWindows from './send-to-all-windows';
|
||||
const { app, nativeTheme, ipcMain, remote } = require('electron');
|
||||
import { app, nativeTheme, ipcMain, remote } from 'electron';
|
||||
|
||||
// scope
|
||||
const v = '2018.2';
|
||||
|
||||
const getDefaultDownloadsPath = () => path.join(app.getPath('home'), 'Downloads');
|
||||
const getDefaultDownloadsPath = () => path.join((app || remote.app).getPath('home'), 'Downloads');
|
||||
|
||||
const getDefaultPauseNotificationsByScheduleFrom = () => {
|
||||
const d = new Date();
|
||||
|
|
@ -27,7 +27,7 @@ const getDefaultPauseNotificationsByScheduleTo = () => {
|
|||
|
||||
const defaultPreferences = {
|
||||
allowNodeInJsCodeInjection: false,
|
||||
allowPrerelease: Boolean(semver.prerelease(app.getVersion())),
|
||||
allowPrerelease: Boolean(semver.prerelease((app || remote.app).getVersion())),
|
||||
askForDownloadPath: true,
|
||||
attachToMenubar: false,
|
||||
blockAds: false,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import { BrowserView, BrowserWindow, app, session, shell, dialog, ipcMain } from 'electron';
|
||||
import path from 'path';
|
||||
import fsExtra from 'fs-extra';
|
||||
import { ElectronBlocker } from '@cliqz/adblocker-electron';
|
||||
import index18n from './i18n';
|
||||
import wikiStartup from './wiki/wiki-startup';
|
||||
import { getPreferences, getPreference } from './preferences';
|
||||
|
|
@ -10,7 +9,10 @@ import { getWorkspace, setWorkspace, getActiveWorkspace } from './workspaces';
|
|||
import { setWorkspaceMeta, getWorkspaceMetas, getWorkspaceMeta } from './workspace-metas';
|
||||
import sendToAllWindows from './send-to-all-windows';
|
||||
import getViewBounds from './get-view-bounds';
|
||||
import customizedFetch from './customized-fetch';
|
||||
|
||||
declare const WEB_VIEW_WEBPACK_ENTRY: string;
|
||||
declare const WEB_VIEW_PRELOAD_WEBPACK_ENTRY: string;
|
||||
|
||||
const views = {};
|
||||
let shouldMuteAudio: any;
|
||||
let shouldPauseNotifications: any;
|
||||
|
|
@ -82,7 +84,6 @@ export const addView = async (browserWindow: any, workspace: any) => {
|
|||
return;
|
||||
}
|
||||
const {
|
||||
blockAds,
|
||||
customUserAgent,
|
||||
proxyBypassRules,
|
||||
proxyPacScript,
|
||||
|
|
@ -122,17 +123,6 @@ export const addView = async (browserWindow: any, workspace: any) => {
|
|||
proxyBypassRules,
|
||||
});
|
||||
}
|
||||
// blocker
|
||||
if (blockAds) {
|
||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '(url: any, _options: any, ...arg... Remove this comment to see the full error message
|
||||
ElectronBlocker.fromPrebuiltAdsAndTracking(customizedFetch, {
|
||||
path: path.join(app.getPath('userData'), 'adblocker.bin'),
|
||||
read: fsExtra.readFile,
|
||||
write: fsExtra.writeFile,
|
||||
}).then((blocker: any) => {
|
||||
blocker.enableBlockingInSession(ses);
|
||||
});
|
||||
}
|
||||
// spellchecker
|
||||
if (spellcheck && process.platform !== 'darwin') {
|
||||
ses.setSpellCheckerLanguages(spellcheckLanguages);
|
||||
|
|
@ -144,7 +134,7 @@ export const addView = async (browserWindow: any, workspace: any) => {
|
|||
contextIsolation: true,
|
||||
enableRemoteModule: true,
|
||||
session: ses,
|
||||
preload: path.join(__dirname, '..', 'preload', 'view.js'),
|
||||
preload: WEB_VIEW_PRELOAD_WEBPACK_ENTRY,
|
||||
};
|
||||
const view = new BrowserView({
|
||||
webPreferences: sharedWebPreferences,
|
||||
|
|
|
|||
|
|
@ -26,9 +26,7 @@ const wikiWorkers = {};
|
|||
// don't forget to config option in `dist.js` https://github.com/electron/electron/issues/18540#issuecomment-652430001
|
||||
// to copy all worker.js and its local dependence to `process.resourcesPath`
|
||||
// On dev, this file will be in .webpack/main/index.js ,so:
|
||||
const WIKI_WORKER_PATH = isDev
|
||||
? path.resolve(__dirname, '..', '..', 'src', 'services', 'libs', 'wiki', './wiki-worker.js')
|
||||
: path.resolve(process.resourcesPath, 'app.asar.unpacked', 'wiki-worker.js');
|
||||
const WIKI_WORKER_PATH = isDev ? path.resolve(__dirname, './wiki-worker.js') : path.resolve(process.resourcesPath, 'app.asar.unpacked', 'wiki-worker.js');
|
||||
export function startWiki(homePath: any, tiddlyWikiPort: any, userName: any) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// require here to prevent circular dependence, which will cause "TypeError: getWorkspaceByName is not a function"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const { MenuItem, shell } = remote;
|
|||
// @ts-expect-error ts-migrate(2322) FIXME: Type '{}' is not assignable to type 'Global & type... Remove this comment to see the full error message
|
||||
window.global = {};
|
||||
let handled = false;
|
||||
const handleLoaded = (event: any) => {
|
||||
const handleLoaded = (event: string) => {
|
||||
if (handled) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ export const get = (): BrowserWindow | undefined => {
|
|||
return win;
|
||||
};
|
||||
|
||||
export const createAsync = () =>
|
||||
new Promise<void>((resolve) => {
|
||||
export const createAsync = async (): Promise<void> =>
|
||||
await new Promise<void>((resolve) => {
|
||||
attachToMenubar = getPreference('attachToMenubar');
|
||||
if (attachToMenubar) {
|
||||
const menubarWindowState = windowStateKeeper({
|
||||
|
|
@ -249,7 +249,7 @@ export const createAsync = () =>
|
|||
resolve();
|
||||
});
|
||||
|
||||
win.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
|
||||
void win.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
|
||||
});
|
||||
|
||||
export const show = () => {
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
// "outDir": "./", /* Redirect output structure to the directory. */
|
||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
|
||||
/* Advanced Options */
|
||||
"skipLibCheck": true, /* Skip type checking of declaration files. */
|
||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||
}
|
||||
}
|
||||
|
|
@ -14,4 +14,8 @@ module.exports = {
|
|||
alias: webpackAlias,
|
||||
extensions: ['.js', '.ts', '.jsx', '.tsx', '.json'],
|
||||
},
|
||||
node: {
|
||||
__filename: true,
|
||||
__dirname: true,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@ module.exports = {
|
|||
plugins: plugins,
|
||||
resolve: {
|
||||
alias: webpackAlias,
|
||||
extensions: ['.js', '.ts', '.jsx', '.tsx'],
|
||||
extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'],
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ module.exports = [
|
|||
// },
|
||||
// },
|
||||
// },
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
|
||||
},
|
||||
{
|
||||
test: /\.(t|j)sx?$/,
|
||||
exclude: /(node_modules|\.webpack)/,
|
||||
|
|
@ -37,4 +41,32 @@ module.exports = [
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif)$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[ext]',
|
||||
outputPath: 'images/',
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'image-webpack-loader',
|
||||
options: {
|
||||
query: {
|
||||
mozjpeg: {
|
||||
progressive: true,
|
||||
},
|
||||
gifsicle: {
|
||||
interlaced: true,
|
||||
},
|
||||
optipng: {
|
||||
optimizationLevel: 7,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue