From 8549da1a17d946b4cc272d8baf9d4ad64fe4e458 Mon Sep 17 00:00:00 2001 From: Maxime GRIS Date: Mon, 1 May 2017 14:08:41 +0200 Subject: [PATCH] Fix webpack prod/dev env --- README.md | 4 +- package.json | 15 +- .../{environment.prod.ts => index.prod.ts} | 0 src/environments/{environment.ts => index.ts} | 0 src/main.ts | 2 +- tsconfig.json | 3 + webpack.config.js | 273 +++++++++++------- 7 files changed, 182 insertions(+), 115 deletions(-) rename src/environments/{environment.prod.ts => index.prod.ts} (100%) rename src/environments/{environment.ts => index.ts} (100%) diff --git a/README.md b/README.md index 7c6746417..1b98e209e 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,9 @@ You can desactivate "Developer Tools" by commenting `win.webContents.openDevTool ## To build for production -- npm run electron:dist +* Using development variables (environments/index.ts) : `npm run electron:dev` + +* Using production variables (environments/index.prod.ts) : `npm run electron:prod` Your built files are in the /dist folder. diff --git a/package.json b/package.json index 0f4701ad2..3a5f125c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-electron", - "version": "1.2.1", + "version": "1.3.0", "description": "Angular 4 with Electron (Typescript + SASS + Hot Reload)", "homepage": "https://github.com/maximegris/angular-electron", "author": { @@ -21,14 +21,16 @@ "test": "karma start ./karma.conf.js", "lint": "ng lint", "e2e": "protractor ./protractor.conf.js", - "build": "webpack && copyfiles main.js dist", + "build": "webpack --display-error-details && copyfiles main.js dist", + "build:prod": "cross-env NODE_ENV='production' npm run build", "prepree2e": "npm start", "pree2e": "webdriver-manager update --standalone false --gecko false --quiet", "electron:serve": "electron . --serve", - "electron:dist": "npm run build && electron dist/main.js", - "electron:linux": "npm run build && copyfiles package.json dist && electron-packager dist --overwrite --platform=linux --arch=x64 --asar=true --out=app-builds", - "electron:windows": "npm run build && copyfiles package.json dist && electron-packager dist --overwrite --platform=win32 --arch=ia32 --asar=true --out=app-builds", - "electron:mac": "npm run build && copyfiles package.json dist && electron-packager dist --overwrite --platform=darwin --arch=x64 --asar=true --out=app-builds" + "electron:dev": "npm run build && electron dist/main.js", + "electron:prod": "npm run build:prod && electron dist/main.js", + "electron:linux": "npm run build:prod && copyfiles package.json dist && electron-packager dist --overwrite --platform=linux --arch=x64 --asar=true --out=app-builds", + "electron:windows": "npm run build:prod && copyfiles package.json dist && electron-packager dist --overwrite --platform=win32 --arch=ia32 --asar=true --out=app-builds", + "electron:mac": "npm run build:prod && copyfiles package.json dist && electron-packager dist --overwrite --platform=darwin --arch=x64 --asar=true --out=app-builds" }, "dependencies": { "@angular/common": "~4.0.2", @@ -52,6 +54,7 @@ "autoprefixer": "~6.7.7", "codelyzer": "~2.1.1", "copyfiles": "~1.2.0", + "cross-env": "^4.0.0", "css-loader": "~0.26.1", "cssnano": "~3.10.0", "electron": "~1.6.5", diff --git a/src/environments/environment.prod.ts b/src/environments/index.prod.ts similarity index 100% rename from src/environments/environment.prod.ts rename to src/environments/index.prod.ts diff --git a/src/environments/environment.ts b/src/environments/index.ts similarity index 100% rename from src/environments/environment.ts rename to src/environments/index.ts diff --git a/src/main.ts b/src/main.ts index a9ca1caf8..29cfdb20b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,7 +2,7 @@ import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; +import { environment } from 'environments'; if (environment.production) { enableProdMode(); diff --git a/tsconfig.json b/tsconfig.json index 894d08f95..cb61bb1d9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,6 +10,9 @@ "experimentalDecorators": true, "allowJs": true, "target": "es5", + "paths": { + "environments": [ "./environments" ] + }, "typeRoots": [ "node_modules/@types" ], diff --git a/webpack.config.js b/webpack.config.js index 61921f324..3849265ae 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,13 +1,14 @@ const path = require('path'); +const webpack = require('webpack'); const ProgressPlugin = require('webpack/lib/ProgressPlugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); const autoprefixer = require('autoprefixer'); const postcssUrl = require('postcss-url'); -const { NoEmitOnErrorsPlugin, LoaderOptionsPlugin } = require('webpack'); +const { NoEmitOnErrorsPlugin, LoaderOptionsPlugin, DefinePlugin, HashedModuleIdsPlugin } = require('webpack'); const { GlobCopyWebpackPlugin, BaseHrefWebpackPlugin } = require('@angular/cli/plugins/webpack'); -const { CommonsChunkPlugin } = require('webpack').optimize; +const { CommonsChunkPlugin, UglifyJsPlugin } = require('webpack').optimize; const { AotPlugin } = require('@ngtools/webpack'); const nodeModules = path.join(process.cwd(), 'node_modules'); @@ -15,6 +16,162 @@ const entryPoints = ["inline","polyfills","sw-register","styles","vendor","main" const baseHref = ""; const deployUrl = ""; +const isProd = (process.env.NODE_ENV === 'production'); + +function getPlugins() { + var plugins = []; + + // Always expose NODE_ENV to webpack, you can now use `process.env.NODE_ENV` + // inside your code for any environment checks; UglifyJS will automatically + // drop any unreachable code. + plugins.push(new DefinePlugin({ + "process.env.NODE_ENV": "\"production\"" + })); + + plugins.push(new NoEmitOnErrorsPlugin()); + + plugins.push(new GlobCopyWebpackPlugin({ + "patterns": [ + "assets", + "favicon.ico" + ], + "globOptions": { + "cwd": "C:\\_PROJECTS\\_PERSO\\angular-electron\\src", + "dot": true, + "ignore": "**/.gitkeep" + } + })); + + plugins.push(new ProgressPlugin()); + + plugins.push(new HtmlWebpackPlugin({ + "template": "./src/index.html", + "filename": "./index.html", + "hash": false, + "inject": true, + "compile": true, + "favicon": false, + "minify": false, + "cache": true, + "showErrors": true, + "chunks": "all", + "excludeChunks": [], + "title": "Webpack App", + "xhtml": true, + "chunksSortMode": function sort(left, right) { + let leftIndex = entryPoints.indexOf(left.names[0]); + let rightindex = entryPoints.indexOf(right.names[0]); + if (leftIndex > rightindex) { + return 1; + } + else if (leftIndex < rightindex) { + return -1; + } + else { + return 0; + } + } + })); + + plugins.push(new BaseHrefWebpackPlugin({})); + + plugins.push(new CommonsChunkPlugin({ + "name": "inline", + "minChunks": null + })); + + plugins.push(new CommonsChunkPlugin({ + "name": "vendor", + "minChunks": (module) => module.resource && module.resource.startsWith(nodeModules), + "chunks": [ + "main" + ] + })); + + plugins.push(new ExtractTextPlugin({ + "filename": "[name].bundle.css", + "disable": true + })); + + plugins.push(new LoaderOptionsPlugin({ + "sourceMap": false, + "options": { + "postcss": [ + autoprefixer(), + postcssUrl({"url": (obj) => { + // Only convert root relative URLs, which CSS-Loader won't process into require(). + if (!obj.url.startsWith('/') || obj.url.startsWith('//')) { + return obj.url; + } + if (deployUrl.match(/:\/\//)) { + // If deployUrl contains a scheme, ignore baseHref use deployUrl as is. + return `${deployUrl.replace(/\/$/, '')}${obj.url}`; + } + else if (baseHref.match(/:\/\//)) { + // If baseHref contains a scheme, include it as is. + return baseHref.replace(/\/$/, '') + + `/${deployUrl}/${obj.url}`.replace(/\/\/+/g, '/'); + } + else { + // Join together base-href, deploy-url and the original URL. + // Also dedupe multiple slashes into single ones. + return `/${baseHref}/${deployUrl}/${obj.url}`.replace(/\/\/+/g, '/'); + } + }}) + ], + "sassLoader": { + "sourceMap": false, + "includePaths": [] + }, + "lessLoader": { + "sourceMap": false + }, + "context": "" + } + })); + + if(isProd) { + plugins.push(new HashedModuleIdsPlugin({ + "hashFunction": "md5", + "hashDigest": "base64", + "hashDigestLength": 4 + })); + + plugins.push(new AotPlugin({ + "mainPath": "main.ts", + "hostReplacementPaths": { + "environments/index.ts": "environments/index.prod.ts" + }, + "exclude": [], + "tsConfigPath": "src/tsconfig.app.json" + })); + + plugins.push(new UglifyJsPlugin({ + "mangle": { + "screw_ie8": true + }, + "compress": { + "screw_ie8": true, + "warnings": false + }, + "sourceMap": false + })); + + } else { + plugins.push( new AotPlugin({ + "mainPath": "main.ts", + "hostReplacementPaths": { + "environments/index.ts": "environments/index.ts" + }, + "exclude": [], + "tsConfigPath": "src/tsconfig.app.json", + "skipCodeGeneration": true + })); + } + + return plugins; +} + module.exports = { "devtool": "source-map", "externals": { @@ -24,8 +181,13 @@ module.exports = { "resolve": { "extensions": [ ".ts", - ".js" + ".js", + ".scss" ], + "aliasFields": [], + "alias": { // WORKAROUND See. angular-cli/issues/5433 + "environments": isProd ? path.resolve(__dirname, 'src/environments/index.prod.ts') : path.resolve(__dirname, 'src/environments/index.ts') + }, "modules": [ "./node_modules" ] @@ -189,110 +351,7 @@ module.exports = { } ] }, - "plugins": [ - new NoEmitOnErrorsPlugin(), - new GlobCopyWebpackPlugin({ - "patterns": [ - "assets", - "favicon.ico" - ], - "globOptions": { - "cwd": "C:\\_PROJECTS\\_PERSO\\angular-electron\\src", - "dot": true, - "ignore": "**/.gitkeep" - } - }), - new ProgressPlugin(), - new HtmlWebpackPlugin({ - "template": "./src/index.html", - "filename": "./index.html", - "hash": false, - "inject": true, - "compile": true, - "favicon": false, - "minify": false, - "cache": true, - "showErrors": true, - "chunks": "all", - "excludeChunks": [], - "title": "Webpack App", - "xhtml": true, - "chunksSortMode": function sort(left, right) { - let leftIndex = entryPoints.indexOf(left.names[0]); - let rightindex = entryPoints.indexOf(right.names[0]); - if (leftIndex > rightindex) { - return 1; - } - else if (leftIndex < rightindex) { - return -1; - } - else { - return 0; - } - } - }), - new BaseHrefWebpackPlugin({}), - new CommonsChunkPlugin({ - "name": "inline", - "minChunks": null - }), - new CommonsChunkPlugin({ - "name": "vendor", - "minChunks": (module) => module.resource && module.resource.startsWith(nodeModules), - "chunks": [ - "main" - ] - }), - new ExtractTextPlugin({ - "filename": "[name].bundle.css", - "disable": true - }), - new LoaderOptionsPlugin({ - "sourceMap": false, - "options": { - "postcss": [ - autoprefixer(), - postcssUrl({"url": (obj) => { - // Only convert root relative URLs, which CSS-Loader won't process into require(). - if (!obj.url.startsWith('/') || obj.url.startsWith('//')) { - return obj.url; - } - if (deployUrl.match(/:\/\//)) { - // If deployUrl contains a scheme, ignore baseHref use deployUrl as is. - return `${deployUrl.replace(/\/$/, '')}${obj.url}`; - } - else if (baseHref.match(/:\/\//)) { - // If baseHref contains a scheme, include it as is. - return baseHref.replace(/\/$/, '') + - `/${deployUrl}/${obj.url}`.replace(/\/\/+/g, '/'); - } - else { - // Join together base-href, deploy-url and the original URL. - // Also dedupe multiple slashes into single ones. - return `/${baseHref}/${deployUrl}/${obj.url}`.replace(/\/\/+/g, '/'); - } - }}) - ], - "sassLoader": { - "sourceMap": false, - "includePaths": [] - }, - "lessLoader": { - "sourceMap": false - }, - "context": "" - } - }), - new AotPlugin({ - "mainPath": "main.ts", - "hostReplacementPaths": { - "environments/environment.ts": "environments/environment.ts" - }, - "exclude": [], - "tsConfigPath": "src/tsconfig.app.json", - "skipCodeGeneration": true - }) - ], + "plugins": getPlugins(), "node": { "fs": "empty", "global": true,