├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── bin └── ngw ├── lib ├── index.ts └── set-up.ts ├── package.json ├── static └── ngw.config.ts ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | *.js -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | lib/*.ts 4 | 5 | typings.d.ts 6 | tsconfig.json 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | language: node_js 4 | sudo: true 5 | node_js: 6 | - "10.12" 7 | install: 8 | - npm i 9 | - npm run build 10 | - rm -rf ./node_modules 11 | - npm i --production 12 | before_script: 13 | - npm i -g @angular/cli 14 | - set -e 15 | - cp -rf "$PWD" ~/ngw 16 | - cd ~ 17 | - ng new test-project --skip-install --defaults=true 18 | - cd test-project 19 | - npm i 20 | - cp -rf "../ngw" "./node_modules/ngw" 21 | - ln -sr "./node_modules/ngw/bin/ngw" "./node_modules/.bin/ngw" 22 | script: 23 | - "grep 'angular.*: \"' package-lock.json | sort -u" 24 | - ./node_modules/.bin/ngw --set-up 25 | - npm run build | fgrep ngw.config 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Angular-RU Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular CLI Webpack (ngw) 2 | 3 | > This package provides an opportunity to modify @angular/cli project's webpack configuration without ["ejecting"](https://github.com/angular/angular-cli/wiki/eject). 4 | 5 | [![Build Status](https://api.travis-ci.org/Angular-RU/angular-cli-webpack.svg?branch=master)](https://travis-ci.org/Angular-RU/angular-cli-webpack) [![npm version](https://badge.fury.io/js/ngw.svg)](https://badge.fury.io/js/ngw) [![dependencies Status](https://david-dm.org/angular-ru/angular-cli-webpack/status.svg)](https://david-dm.org/angular-ru/angular-cli-webpack) 6 | [![Coverage Status](https://coveralls.io/repos/github/Angular-RU/angular-cli-webpack/badge.svg?branch=master)](https://coveralls.io/github/Angular-RU/angular-cli-webpack?branch=master) [![Coverage Status](https://img.shields.io/npm/dt/ngw.svg)](https://npm-stat.com/charts.html?package=ngw&from=2017-01-12) 7 | 8 | ## Installation 9 | For angular 6/7: 10 | ```bash 11 | $ npx -p @angular/cli ng new my-project && cd my-project # create new Angular CLI project 12 | $ npm i -D ngw # installing an improved cli-eject 13 | $ ./node_modules/.bin/ngw --set-up # run via terminal in project root 14 | Set up went successfully! 15 | ``` 16 | For angular 5 use `npm i -D ngw@angular5` 17 | ## Usage: 18 | Last command installation (ngw --set-up) makes three things: 19 | 1) Changes scripts in package.json that starts from `ng ` to `ngw ` 20 | 2) Creates file `ngw.config.ts` in project root where you can redefine `webpack.Configuration` used by `@angular/cli` 21 | 3) Sets `compilerOptions.module = "commonjs"` property in `tsconfig.json` 22 | 23 | So just make changes to the webpack config in appeared `ngw.config.ts` 24 | 25 | You may like to do `npm i -D @types/webpack` for better experience. 26 | 27 | ## Example 28 | 29 | #### Removes unused selectors from your CSS 30 | 31 | This little piece of code in your ngw.config [removes unused selectors from your CSS:](https://github.com/webpack-contrib/purifycss-webpack) 32 | 33 | ```typescript 34 | const PurifyCSSPlugin = require('purifycss-webpack'); 35 | const path = require('path'); 36 | const glob = require('glob'); 37 | 38 | export default function(config) { 39 | config.plugins.push( 40 | new PurifyCSSPlugin({ 41 | paths: glob.sync(path.join(__dirname, '**/*.html')) 42 | }) 43 | ); 44 | return config; 45 | } 46 | ``` 47 | ## Debugging 48 | You may like to debug your configuration. 49 | This can be done with [ndb](https://github.com/GoogleChromeLabs/ndb) package. 50 | 1) Make sure that your development environment meets the requirements of `ndb` 51 | 2) `npm i -g ndb` 52 | 3) Add `debugger` keyword in `ngw.config.ts` 53 | 4) `ndb npm run start` 54 | 55 | ## Prod and dev mode modifications (ngw.config.ts) 56 | ```typescript 57 | 58 | const isProduction = process.argv.indexOf('--prod') !== -1; 59 | 60 | export default function(config, options) { 61 | //common config modification 62 | ... 63 | config = isProduction 64 | ? productionModificationsMerged(config) 65 | : devModificationsMerged(config); 66 | } 67 | ... 68 | } 69 | ``` 70 | -------------------------------------------------------------------------------- /bin/ngw: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | switch (process.argv[2]) { 3 | case '--set-up': 4 | require('../lib/set-up'); 5 | break; 6 | default: 7 | 8 | const execSync = require('child_process').execSync; 9 | const entryPointPath = require.resolve('../lib/index'); 10 | const tsNodePath = require.resolve('ts-node/dist/bin'); 11 | const ngCommandArgs = process.argv.slice(2); 12 | const executionPoint = [tsNodePath, entryPointPath].concat(ngCommandArgs).join('" "'); 13 | 14 | execSync(`node "${executionPoint}"`, {stdio: 'inherit'}); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /lib/index.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import { BrowserBuilder } from '@angular-devkit/build-angular/src/browser/index'; 3 | import { ServerBuilder } from '@angular-devkit/build-angular/src/server/index'; 4 | import { KarmaBuilder } from '@angular-devkit/build-angular/src/karma/index'; 5 | import { ExtractI18nBuilder } from '@angular-devkit/build-angular/src/extract-i18n/index'; 6 | import { WebpackOptions } from '../static/ngw.config'; 7 | 8 | const configClasses = { 9 | 'browser': BrowserBuilder, 10 | 'server': ServerBuilder, 11 | 'karma': KarmaBuilder, 12 | 'extract-i18n': ExtractI18nBuilder 13 | }; 14 | const configClassNames = { 15 | 'browser': 'BrowserBuilder', 16 | 'server': 'ServerBuilder', 17 | 'karma': 'KarmaBuilder', 18 | 'extract-i18n': 'ExtractI18nBuilder' 19 | }; 20 | 21 | Object.keys(configClasses).forEach(buildConfig); 22 | 23 | function buildConfig(variant: string) { 24 | const methodName = configClasses[variant].prototype.hasOwnProperty('_buildWebpackConfig') 25 | ? '_buildWebpackConfig' 26 | : 'buildWebpackConfig'; 27 | 28 | configClasses[variant].prototype.buildConfigInner = configClasses[variant].prototype[methodName]; 29 | configClasses[variant].prototype[methodName] = configClasses[variant].prototype.buildConfig = function (...args) { 30 | const config = this.buildConfigInner(...args); 31 | 32 | try { 33 | const interceptorPath = path.resolve('./ngw.config'); 34 | const interceptor = require(interceptorPath).default; 35 | const options: WebpackOptions = { 36 | root: args[0], 37 | projectRoot: args[1], 38 | options: args[args.length - 1] 39 | }; 40 | return interceptor(config, options); 41 | } catch (e) { 42 | console.dir(e); 43 | if (e.code === 'MODULE_NOT_FOUND') { 44 | console.warn('ngw.config file is not found at serving directory. Starting common build'); 45 | return config; 46 | } else { throw e; } 47 | 48 | } 49 | }; 50 | 51 | const webpackConfig = require.resolve(`@angular-devkit/build-angular/src/${variant}/index`); 52 | require.cache[webpackConfig][configClassNames[variant]] = configClasses[variant]; 53 | } 54 | 55 | require('@angular/cli/bin/ng'); 56 | -------------------------------------------------------------------------------- /lib/set-up.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | 3 | let packageJsonFile; 4 | let tsConfigFile; 5 | try { 6 | packageJsonFile = fs.readFileSync('package.json', 'utf-8'); 7 | tsConfigFile = fs.readFileSync('tsconfig.json', 'utf-8'); 8 | } catch (e) { 9 | throw new Error('Cannot find package.json or tsconfig.json in the execution folder'); 10 | } 11 | const packageJson = JSON.parse(packageJsonFile.replace(/^\uFEFF/, '')); 12 | Object.keys(packageJson.scripts) 13 | .map(function (x) { 14 | return packageJson.scripts[x] = 15 | packageJson.scripts[x].slice(0, 3) === 'ng ' ? 16 | 'ngw ' + packageJson.scripts[x].slice(3) : 17 | packageJson.scripts[x]; 18 | }); 19 | 20 | const tsConfig = JSON.parse(tsConfigFile.replace(/^\uFEFF/, '')); 21 | tsConfig.compilerOptions.module = 'commonjs'; 22 | 23 | fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2) + '\n'); 24 | fs.writeFileSync('tsconfig.json', JSON.stringify(tsConfig, null, 2) + '\n'); 25 | fs.writeFileSync('ngw.config.ts', fs.readFileSync((require.resolve('../static/ngw.config.ts')))); 26 | console.log('Set up went successfully!'); 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngw", 3 | "version": "7.0.0", 4 | "description": "Provides an opportunity to overload webpack config for angular-cli applications", 5 | "main": "lib/index.js", 6 | "typings": "lib/index", 7 | "scripts": { 8 | "lint": "tslint -c tslint.json 'src/**/*.ts'", 9 | "test": "echo test", 10 | "coverage": "echo coverage", 11 | "build": "tsc", 12 | "prepublishOnly": "tsc" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/Angular-RU/ngw.git" 17 | }, 18 | "author": "", 19 | "bin": { 20 | "ngw": "./bin/ngw" 21 | }, 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/Angular-RU/ngw/issues" 25 | }, 26 | "homepage": "https://github.com/Angular-RU/ngw#readme", 27 | "peerDependencies": { 28 | "@types/node": "*", 29 | "@types/webpack": "*" 30 | }, 31 | "dependencies": { 32 | "ts-node": "^7.0.1", 33 | "typescript": "^3.0.0" 34 | }, 35 | "devDependencies": { 36 | "@angular-devkit/build-angular": "0.6.7", 37 | "@angular-devkit/core": "0.6.7", 38 | "@types/node": "^9.4.6", 39 | "@types/webpack": "^3.0.0", 40 | "tslint": "^5.8.0", 41 | "tslint-config-standard": "^7.0.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /static/ngw.config.ts: -------------------------------------------------------------------------------- 1 | import * as webpack from 'webpack'; 2 | import { Path } from '@angular-devkit/core'; 3 | import { NormalizedBrowserBuilderSchema } from '@angular-devkit/build-angular'; 4 | 5 | export interface WebpackOptions { 6 | root: Path; 7 | projectRoot: Path; 8 | options: T; 9 | } 10 | 11 | const command = process.argv[2].toLowerCase(); 12 | 13 | export default function (config: webpack.Configuration, options: WebpackOptions) { 14 | if (command === 'test') { 15 | console.log('Test configuration is running'); 16 | } 17 | console.log('To modify webpack build, you can use ngw.config.ts'); 18 | return config; 19 | } 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "lib": [ 6 | "es2015", 7 | "es2017", 8 | "dom" 9 | ], 10 | "noImplicitAny": false, 11 | "sourceMap": false, 12 | "declaration": false, 13 | "strictNullChecks": false, 14 | "suppressImplicitAnyIndexErrors": false, 15 | "moduleResolution": "node", 16 | "skipLibCheck": true 17 | }, 18 | "exclude": [ 19 | "node_modules", 20 | "static" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint:recommended" 4 | ], 5 | "rules": { 6 | "no-var-requires": false, 7 | "prefer-for-of": false, 8 | "trailing-comma": [ 9 | false, 10 | { 11 | "multiline": "always", 12 | "singleline": "never" 13 | } 14 | ], 15 | "interface-name": [ 16 | false, 17 | "always-prefix" 18 | ], 19 | "arrow-return-shorthand": true, 20 | "callable-types": true, 21 | "class-name": true, 22 | "comment-format": [ 23 | true, 24 | "check-space" 25 | ], 26 | "curly": true, 27 | "eofline": true, 28 | "forin": true, 29 | "import-blacklist": [ 30 | true, 31 | "rxjs", 32 | "rxjs/Rx" 33 | ], 34 | "import-spacing": true, 35 | "indent": [ 36 | true, 37 | "spaces", 38 | 4 39 | ], 40 | "interface-over-type-literal": true, 41 | "only-arrow-functions": false, 42 | "label-position": true, 43 | "max-line-length": [ 44 | true, 45 | 200 46 | ], 47 | "member-access": false, 48 | "ordered-imports": false, 49 | "member-ordering": [ 50 | true, 51 | { 52 | "order": [ 53 | "static-field", 54 | "instance-field", 55 | "static-method", 56 | "instance-method" 57 | ] 58 | } 59 | ], 60 | "no-arg": true, 61 | "no-bitwise": true, 62 | "no-console": [ 63 | true, 64 | "debug", 65 | "info", 66 | "time", 67 | "timeEnd", 68 | "trace" 69 | ], 70 | "no-construct": true, 71 | "no-debugger": true, 72 | "no-duplicate-super": true, 73 | "no-empty": false, 74 | "no-empty-interface": true, 75 | "no-eval": true, 76 | "no-inferrable-types": [ 77 | true, 78 | "ignore-params", 79 | "ignore-properties" 80 | ], 81 | "no-misused-new": true, 82 | "no-non-null-assertion": true, 83 | "no-shadowed-variable": true, 84 | "no-string-literal": false, 85 | "no-string-throw": true, 86 | "no-switch-case-fall-through": true, 87 | "no-trailing-whitespace": true, 88 | "no-unnecessary-initializer": true, 89 | "no-unused-expression": true, 90 | "no-var-keyword": true, 91 | "object-literal-sort-keys": false, 92 | "space-before-function-paren": [ 93 | true, 94 | { 95 | "anonymous": "always", 96 | "named": "never", 97 | "asyncArrow": "always" 98 | } 99 | ], 100 | "one-line": [ 101 | true, 102 | "check-open-brace", 103 | "check-catch", 104 | "check-else", 105 | "check-whitespace" 106 | ], 107 | "prefer-const": true, 108 | "quotemark": [ 109 | true, 110 | "single" 111 | ], 112 | "radix": false, 113 | "semicolon": [ 114 | true, 115 | "always" 116 | ], 117 | "triple-equals": [ 118 | true, 119 | "allow-null-check" 120 | ], 121 | "typedef-whitespace": [ 122 | true, 123 | { 124 | "call-signature": "nospace", 125 | "index-signature": "nospace", 126 | "parameter": "nospace", 127 | "property-declaration": "nospace", 128 | "variable-declaration": "nospace" 129 | } 130 | ], 131 | "unified-signatures": true, 132 | "variable-name": false, 133 | "whitespace": [ 134 | true, 135 | "check-branch", 136 | "check-decl", 137 | "check-operator", 138 | "check-separator", 139 | "check-type", 140 | "check-module", 141 | "check-preblock", 142 | "check-typecast" 143 | ], 144 | "no-input-rename": false, 145 | "no-output-rename": false, 146 | "use-life-cycle-interface": false, 147 | "component-class-suffix": false, 148 | "directive-class-suffix": false 149 | } 150 | } 151 | --------------------------------------------------------------------------------