Skip to content

Commit

Permalink
Adding Electron target
Browse files Browse the repository at this point in the history
  • Loading branch information
rorticus committed Sep 9, 2020
1 parent 65dd5e9 commit cf1874b
Show file tree
Hide file tree
Showing 9 changed files with 651 additions and 109 deletions.
526 changes: 459 additions & 67 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
"tslint": "5.18.0"
},
"dependencies": {
"@dojo/webpack-contrib": "~7.0.3",
"@dojo/webpack-contrib": "8.0.0-alpha.1",
"@typescript-eslint/eslint-plugin": "2.34.0",
"@typescript-eslint/parser": "2.34.0",
"caniuse-lite": "1.0.30000973",
Expand All @@ -119,6 +119,7 @@
"css-loader": "1.0.1",
"css-url-relative-plugin": "1.0.0",
"cssnano": "4.1.7",
"electron": "10.1.1",
"eslint": "7.0.0",
"eslint-loader": "4.0.2",
"eslint-plugin-jsdoc": "25.4.2",
Expand Down
3 changes: 2 additions & 1 deletion src/base.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ export class InsertScriptPlugin {
export default function webpackConfigFactory(args: any): webpack.Configuration {
tsnode.register({ transpileOnly: true });
const isLegacy = args.legacy;
const base = args.target === 'electron' ? './' : args.base || '/';
const experimental = args.experimental || {};
const isExperimentalSpeed = !!experimental.speed && args.mode === 'dev';
const isTest = args.mode === 'unit' || args.mode === 'functional' || args.mode === 'test';
Expand Down Expand Up @@ -544,7 +545,7 @@ export default function webpackConfigFactory(args: any): webpack.Configuration {
files: watchExtraFiles
}),
new ManifestPlugin(),
new CssUrlRelativePlugin({ root: args.base || '/' })
new CssUrlRelativePlugin({ root: base || '/' })
]),
module: {
// `file` uses the pattern `loaderPath!filePath`, hence the regex test
Expand Down
2 changes: 1 addition & 1 deletion src/dev.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function webpackConfig(args: any): webpack.Configuration {
const experimental = args.experimental || {};
const isExperimentalSpeed = !!experimental.speed;
const singleBundle = args.singleBundle || isExperimentalSpeed;
const base = args.base || '/';
const base = args.target === 'electron' ? './' : args.base || '/';

const basePath = process.cwd();
const config = baseConfigFactory(args);
Expand Down
2 changes: 1 addition & 1 deletion src/dist.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ All rights reserved

function webpackConfig(args: any): webpack.Configuration {
const basePath = process.cwd();
const base = args.base || '/';
const base = args.target === 'electron' ? './' : args.base || '/';
const config = baseConfigFactory(args);
const manifest: WebAppManifest = args.pwa && args.pwa.manifest;
const { plugins, output } = config;
Expand Down
94 changes: 94 additions & 0 deletions src/electron.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import ElectronPlugin from '@dojo/webpack-contrib/electron-plugin/ElectronPlugin';
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

import * as webpack from 'webpack';
import * as path from 'path';
import * as fs from 'fs';

const basePath = process.cwd();
const srcPath = path.join(basePath, 'src');
const extensions = ['.ts', '.tsx', '.mjs', '.js'];
const removeEmpty = (items: any[]) => items.filter((item) => item);
const mainPath = path.join(srcPath, 'main.electron.ts');

function webpackConfig(args: any): webpack.Configuration {
const experimental = args.experimental || {};
const electron = args.electron || {};
const isExperimentalSpeed = !!experimental.speed && args.mode === 'dev';
const baseOutputPath = path.resolve('./output');
const outputPath = path.join(baseOutputPath, args.mode);

return {
name: 'electron',
entry: {
'main.electron': removeEmpty([
'@dojo/webpack-contrib/electron-plugin/bootstrap',
fs.existsSync(mainPath) ? mainPath : null
])
},
resolveLoader: {
modules: [path.resolve(__dirname, 'node_modules'), 'node_modules']
},
resolve: {
modules: [basePath, path.join(basePath, 'node_modules')],
extensions,
plugins: [new TsconfigPathsPlugin({ configFile: path.join(basePath, 'tsconfig.json') })]
},
mode: args.mode === 'dev' ? 'development' : 'production',
devtool: 'source-map',
watchOptions: { ignored: /node_modules/ },
target: 'electron-main',
plugins: [
new ElectronPlugin({
electron: {
browser: electron.browser || {},
packaging: electron.packaging || {}
},
watch: !!args.watch,
serve: !!args.serve,
port: args.port,
dist: args.mode !== 'dev'
} as any)
],
module: {
rules: [
{
test: /\.(gif|png|jpe?g|svg|eot|ttf|woff|woff2|ico)$/i,
loader: 'file-loader?hash=sha512&digest=hex&name=[name].[hash:base64:8].[ext]'
},
{
test: /@dojo(\/|\\).*\.(js|mjs)$/,
enforce: 'pre',
loader: 'source-map-loader-cli',
options: { includeModulePaths: true }
},
{
include: srcPath,
test: /\.ts(x)?$/,
use: removeEmpty([
{
loader: 'ts-loader',
options: {
onlyCompileBundledFiles: true,
instance: 'dojo',
transpileOnly: isExperimentalSpeed,
compilerOptions: {
target: 'es2017',
module: 'esnext',
downlevelIteration: false
}
}
}
])
}
]
},
output: {
chunkFilename: '[name].js',
filename: '[name].js',
path: outputPath
}
};
}

export default webpackConfig;
80 changes: 49 additions & 31 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ import devConfigFactory from './dev.config';
import unitConfigFactory from './unit.config';
import functionalConfigFactory from './functional.config';
import distConfigFactory from './dist.config';
import electronConfigFactory from './electron.config';
import logger from './logger';
import { moveBuildOptions } from './util/eject';
import { readFileSync } from 'fs';

export const mainEntry = 'main';
const packageJsonPath = path.join(process.cwd(), 'package.json');
const packageJson = fs.existsSync(packageJsonPath) ? require(packageJsonPath) : {};
export const packageName = packageJson.name || '';
Expand All @@ -37,20 +37,19 @@ function getLibraryName(name: string) {

const libraryName = packageName ? getLibraryName(packageName) : 'main';

const fixMultipleWatchTrigger = require('webpack-mild-compile');
const hotMiddleware = require('webpack-hot-middleware');
const connectInject = require('connect-inject');

const testModes = ['test', 'unit', 'functional'];

function createCompiler(config: webpack.Configuration) {
const compiler = webpack(config);
fixMultipleWatchTrigger(compiler);
return compiler;
// for some reason the MultiCompiler type doesn't include hooks, even though they are clearly defined on the
// object coming back.
interface MultiCompilerWithHooks extends webpack.MultiCompiler {
hooks: webpack.compilation.CompilerHooks;
}

function createWatchCompiler(config: webpack.Configuration) {
const compiler = createCompiler(config);
function createWatchCompiler(configs: webpack.Configuration[]) {
const compiler = webpack(configs) as MultiCompilerWithHooks;
const spinner = ora('building').start();
compiler.hooks.invalid.tap('@dojo/cli-build-app', () => {
logUpdate('');
Expand Down Expand Up @@ -83,18 +82,18 @@ function serveStatic(
}
}

function build(config: webpack.Configuration, args: any) {
const compiler = createCompiler(config);
function build(configs: webpack.Configuration[], args: any) {
const compiler = webpack(configs);
const spinner = ora('building').start();
return new Promise<webpack.Compiler>((resolve, reject) => {
return new Promise<webpack.MultiCompiler>((resolve, reject) => {
compiler.run((err, stats) => {
spinner.stop();
if (err) {
reject(err);
}
if (stats) {
const runningMessage = args.serve ? `Listening on port ${args.port}...` : '';
const hasErrors = logger(stats.toJson({ warningsFilter }), config, runningMessage, args);
const hasErrors = logger(stats.toJson({ warningsFilter }), configs, runningMessage, args);
if (hasErrors) {
reject({});
return;
Expand Down Expand Up @@ -125,10 +124,15 @@ function buildNpmDependencies(): any {
}
}

async function fileWatch(config: webpack.Configuration, args: any, shouldResolve = false) {
return new Promise<webpack.Compiler>((resolve, reject) => {
const watchOptions = config.watchOptions as webpack.Compiler.WatchOptions;
const compiler = createWatchCompiler(config);
function fileWatch(configs: webpack.Configuration[], args: any, shouldResolve = false): Promise<webpack.MultiCompiler> {
const [mainConfig] = configs;
let compiler: webpack.MultiCompiler;

return new Promise<webpack.MultiCompiler>((resolve, reject) => {
const watchOptions = mainConfig.watchOptions as webpack.Compiler.WatchOptions;

compiler = createWatchCompiler(configs);

compiler.watch(watchOptions, (err, stats) => {
if (err) {
reject(err);
Expand All @@ -139,7 +143,7 @@ async function fileWatch(config: webpack.Configuration, args: any, shouldResolve
args.port
}\nPlease note the serve option is not intended to be used to serve applications in production.`
: 'watching...';
logger(stats.toJson({ warningsFilter }), config, runningMessage, args);
logger(stats.toJson({ warningsFilter }), configs, runningMessage, args);
}
if (shouldResolve) {
resolve(compiler);
Expand All @@ -148,8 +152,9 @@ async function fileWatch(config: webpack.Configuration, args: any, shouldResolve
});
}

async function serve(config: webpack.Configuration, args: any) {
const compiler = args.watch ? await fileWatch(config, args, true) : await build(config, args);
async function serve(configs: webpack.Configuration[], args: any) {
const [mainConfig] = configs;

let isHttps = false;
const base = args.base || '/';

Expand All @@ -162,19 +167,21 @@ async function serve(config: webpack.Configuration, args: any) {
next();
});

const outputDir = (config.output && config.output.path) || process.cwd();
const compiler = args.watch ? await fileWatch(configs, args, true) : await build(configs, args);

const outputDir = (mainConfig.output && mainConfig.output.path) || process.cwd();
let btrOptions = args['build-time-render'];
if (btrOptions) {
if (args.singleBundle || (args.experimental && !!args.experimental.speed)) {
btrOptions = { ...btrOptions, sync: true };
}
const jsonpName = (config.output && config.output.jsonpFunction) || 'unknown';
const jsonpName = (mainConfig.output && mainConfig.output.jsonpFunction) || 'unknown';
const onDemandBtr = new OnDemandBtr({
buildTimeRenderOptions: btrOptions,
scope: libraryName,
base,
compiler,
entries: config.entry ? Object.keys(config.entry) : [],
compiler: compiler.compilers[0],
entries: mainConfig.entry ? Object.keys(mainConfig.entry) : [],
outputPath: outputDir,
jsonpName
});
Expand Down Expand Up @@ -295,6 +302,13 @@ const command: Command = {
choices: ['dist', 'dev', 'test', 'unit', 'functional']
});

options('target', {
describe: 'the target',
alias: 't',
default: 'web',
choices: ['web', 'electron']
});

options('watch', {
describe: 'watch for file changes',
alias: 'w'
Expand Down Expand Up @@ -355,35 +369,39 @@ const command: Command = {
},
run(helper: Helper, args: any) {
console.log = () => {};
let config: webpack.Configuration;
let configs: webpack.Configuration[] = [];
args.experimental = args.experimental || {};
args.base = url.resolve('/', args.base || '');
if (!args.base.endsWith('/')) {
args.base = `${args.base}/`;
}

if (args.mode === 'dev') {
config = devConfigFactory(args);
configs.push(devConfigFactory(args));
} else if (args.mode === 'unit' || args.mode === 'test') {
config = unitConfigFactory(args);
configs.push(unitConfigFactory(args));
} else if (args.mode === 'functional') {
config = functionalConfigFactory(args);
configs.push(functionalConfigFactory(args));
} else {
config = distConfigFactory(args);
configs.push(distConfigFactory(args));
}

if (args.target === 'electron') {
configs.push(electronConfigFactory(args));
}

if (args.serve) {
if (testModes.indexOf(args.mode) !== -1) {
return Promise.reject(new Error(`Cannot use \`--serve\` with \`--mode=${args.mode}\``));
}
return serve(config, args);
return serve(configs, args);
}

if (args.watch) {
return fileWatch(config, args);
return fileWatch(configs, args);
}

return build(config, args);
return build(configs, args);
},
eject(helper: Helper): EjectOutput {
return {
Expand Down
23 changes: 23 additions & 0 deletions src/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
"functional"
]
},
"target": {
"type": "string",
"enum": [
"web",
"electron"
]
},
"watch": {
"type": "boolean"
},
Expand Down Expand Up @@ -63,6 +70,13 @@
}
}
},
"electron": {
"properties": {
"browser": {
"type": "object"
}
}
},
"build-time-render": {
"additionalProperties": false,
"properties": {
Expand Down Expand Up @@ -445,6 +459,12 @@
"m": {
"$ref": "#/definitions/mode"
},
"target": {
"$ref": "#/definitions/target"
},
"t": {
"$ref": "#/definitions/target"
},
"watch": {
"$ref": "#/definitions/watch"
},
Expand Down Expand Up @@ -522,6 +542,9 @@
{ "$ref": "#/definitions/imageOptimizationOptions" },
{ "$ref": "#/definitions/imageOptimizationFlag" }
]
},
"electron": {
"$ref": "#/definitions/electron"
}
}
}
Loading

0 comments on commit cf1874b

Please sign in to comment.