diff --git a/build/tasks/release-checks/suite-steps.js b/build/tasks/release-checks/suite-steps.js index ce584c821..472911c15 100644 --- a/build/tasks/release-checks/suite-steps.js +++ b/build/tasks/release-checks/suite-steps.js @@ -65,11 +65,11 @@ module.exports = function(suite) { if (applicable(features, 'webpack')) { steps.push( - new tests.webpack.AuRunDoesNotThrowCommandLineErrors(), - new tests.webpack.AuRunLaunchesServer(), - new tests.webpack.AuRunRendersPage(), - new tests.webpack.AuRunAppLaunchesWithoutJavascriptErrors(), - new tests.webpack.AuRunWatchPicksUpFileChanges() + new tests.webpack.NpmStartDoesNotThrowCommandLineErrors(), + new tests.webpack.NpmStartLaunchesServer(), + new tests.webpack.NpmStartRendersPage(), + new tests.webpack.NpmStartAppLaunchesWithoutJavascriptErrors(), + new tests.webpack.NpmStartWatchPicksUpFileChanges() ); } diff --git a/build/tasks/release-checks/tests/generic/au-cypress.js b/build/tasks/release-checks/tests/generic/au-cypress.js index ae0c82f14..be455bfb8 100644 --- a/build/tasks/release-checks/tests/generic/au-cypress.js +++ b/build/tasks/release-checks/tests/generic/au-cypress.js @@ -30,7 +30,7 @@ class AuCypressRunsTests extends Test { } execute() { - this.executeCommand = new ExecuteCommand('au', ['run'], (msg) => this.onOutput(msg)); + this.executeCommand = new ExecuteCommand('npm', ['start'], (msg) => this.onOutput(msg)); return this.executeCommand.executeAsNodeScript(); } } diff --git a/build/tasks/release-checks/tests/generic/au-protractor.js b/build/tasks/release-checks/tests/generic/au-protractor.js index 024dfbe07..07dfd087b 100644 --- a/build/tasks/release-checks/tests/generic/au-protractor.js +++ b/build/tasks/release-checks/tests/generic/au-protractor.js @@ -27,7 +27,7 @@ class AuProtractorRunsTests extends Test { } execute() { - this.executeCommand = new ExecuteCommand('au', ['run'], (msg) => this.onOutput(msg)); + this.executeCommand = new ExecuteCommand('npm', ['start'], (msg) => this.onOutput(msg)); return this.executeCommand.executeAsNodeScript(); } } diff --git a/build/tasks/release-checks/tests/webpack/index.js b/build/tasks/release-checks/tests/webpack/index.js index 1d098164b..1b996242d 100644 --- a/build/tasks/release-checks/tests/webpack/index.js +++ b/build/tasks/release-checks/tests/webpack/index.js @@ -1,3 +1,3 @@ module.exports = { - ...require('./au-run') + ...require('./run') }; diff --git a/build/tasks/release-checks/tests/webpack/au-run.js b/build/tasks/release-checks/tests/webpack/run.js similarity index 73% rename from build/tasks/release-checks/tests/webpack/au-run.js rename to build/tasks/release-checks/tests/webpack/run.js index ccbafa1c1..02b3906c1 100644 --- a/build/tasks/release-checks/tests/webpack/au-run.js +++ b/build/tasks/release-checks/tests/webpack/run.js @@ -6,9 +6,9 @@ const StepRunner = require('../../step-runner'); const path = require('path'); const fs = require('fs'); -class AuRunDoesNotThrowCommandLineErrors extends Test { +class NpmStartDoesNotThrowCommandLineErrors extends Test { constructor() { - super('au run does not throw commandline errors'); + super('npm start does not throw commandline errors'); } onOutput(message) { @@ -24,14 +24,14 @@ class AuRunDoesNotThrowCommandLineErrors extends Test { } execute() { - this.executeCommand = new ExecuteCommand('au', ['run'], (msg) => this.onOutput(msg)); + this.executeCommand = new ExecuteCommand('npm', ['start'], (msg) => this.onOutput(msg)); return this.executeCommand.executeAsNodeScript(); } } -class AuRunLaunchesServer extends Test { +class NpmStartLaunchesServer extends Test { constructor() { - super('au run launches server'); + super('npm start launches server'); } onOutput(message) { @@ -44,14 +44,14 @@ class AuRunLaunchesServer extends Test { } execute() { - this.executeCommand = new ExecuteCommand('au', ['run'], (msg) => this.onOutput(msg)); + this.executeCommand = new ExecuteCommand('npm', ['start'], (msg) => this.onOutput(msg)); return this.executeCommand.executeAsNodeScript(); } } -class AuRunWatchPicksUpFileChanges extends Test { +class NpmStartWatchPicksUpFileChanges extends Test { constructor(fileToChange) { - super('au run picks up file changes'); + super('npm start picks up file changes'); this.fileToChange = fileToChange || path.join('src', 'app.html'); this.watchingForFileChangeNotification = false; @@ -99,14 +99,14 @@ class AuRunWatchPicksUpFileChanges extends Test { execute(context) { this.context = context; - this.executeCommand = new ExecuteCommand('au', ['run'], (msg) => this.onOutput(msg)); + this.executeCommand = new ExecuteCommand('npm', ['start'], (msg) => this.onOutput(msg)); return this.executeCommand.executeAsNodeScript(); } } -class AuRunAppLaunchesWithoutJavascriptErrors extends Test { +class NpmStartAppLaunchesWithoutJavascriptErrors extends Test { constructor() { - super('au run app launches without javascript errors'); + super('npm start app launches without javascript errors'); } onOutput(message) { @@ -126,14 +126,14 @@ class AuRunAppLaunchesWithoutJavascriptErrors extends Test { } execute() { - this.executeCommand = new ExecuteCommand('au', ['run'], (msg) => this.onOutput(msg)); + this.executeCommand = new ExecuteCommand('npm', ['start'], (msg) => this.onOutput(msg)); return this.executeCommand.executeAsNodeScript(); } } -class AuRunRendersPage extends Test { +class NpmStartRendersPage extends Test { constructor() { - super('au run renders page'); + super('npm start renders page'); } onOutput(context, message) { @@ -142,7 +142,7 @@ class AuRunRendersPage extends Test { if (isApplicationAvailableMessage(message)) { const url = getURL(message); - const screenshot = new TakeScreenShotOfPage(url, path.join(context.resultOutputFolder, 'screenshot-of-au-run.png')); + const screenshot = new TakeScreenShotOfPage(url, path.join(context.resultOutputFolder, 'screenshot-of-npm-start.png')); return new StepRunner(screenshot).run() .then(() => { @@ -153,7 +153,7 @@ class AuRunRendersPage extends Test { } execute(context) { - this.executeCommand = new ExecuteCommand('au', ['run'], (msg) => this.onOutput(context, msg)); + this.executeCommand = new ExecuteCommand('npm', ['start'], (msg) => this.onOutput(context, msg)); return this.executeCommand.executeAsNodeScript(); } } @@ -169,9 +169,9 @@ function getURL(msg) { } module.exports = { - AuRunDoesNotThrowCommandLineErrors, - AuRunLaunchesServer, - AuRunWatchPicksUpFileChanges, - AuRunAppLaunchesWithoutJavascriptErrors, - AuRunRendersPage + NpmStartDoesNotThrowCommandLineErrors, + NpmStartLaunchesServer, + NpmStartWatchPicksUpFileChanges, + NpmStartAppLaunchesWithoutJavascriptErrors, + NpmStartRendersPage }; diff --git a/skeleton/common/config/environment.json b/skeleton/common/config/environment.json new file mode 100644 index 000000000..a32129fd0 --- /dev/null +++ b/skeleton/common/config/environment.json @@ -0,0 +1,4 @@ +{ + "debug": true, + "testing": true +} \ No newline at end of file diff --git a/skeleton/common/config/environment.production.json b/skeleton/common/config/environment.production.json new file mode 100644 index 000000000..9ddbb4430 --- /dev/null +++ b/skeleton/common/config/environment.production.json @@ -0,0 +1,4 @@ +{ + "debug": false, + "testing": false +} \ No newline at end of file diff --git a/skeleton/common/tsconfig.json__if_typescript b/skeleton/common/tsconfig.json__if_typescript index fadcfe313..18cfbb56c 100644 --- a/skeleton/common/tsconfig.json__if_typescript +++ b/skeleton/common/tsconfig.json__if_typescript @@ -32,10 +32,8 @@ "types": ["node", "jest"], // @endif - // @if feat.webpack && feat['postcss-typical'] && feat.protractor "typeRoots": ["./node_modules/@types"], - // @endif - + "removeComments": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, @@ -44,6 +42,7 @@ "lib": ["es2015", "dom"], "moduleResolution": "node", "baseUrl": "src", + "resolveJsonModule": true, // @if feat.plugin "paths": { "resources": [ "" ] }, diff --git a/skeleton/scaffold-minimum/src/main.ext b/skeleton/scaffold-minimum/src/main.ext index 7ce184a19..b1d52cffa 100644 --- a/skeleton/scaffold-minimum/src/main.ext +++ b/skeleton/scaffold-minimum/src/main.ext @@ -6,7 +6,7 @@ import 'regenerator-runtime/runtime'; // @if feat.typescript import {Aurelia} from 'aurelia-framework' // @endif -import environment from './environment'; +import * as environment from '../config/environment.json'; // @if feat.webpack import {PLATFORM} from 'aurelia-pal'; // @endif diff --git a/skeleton/scaffold-navigation/src/main.ext b/skeleton/scaffold-navigation/src/main.ext index 7d27096d7..6af74b7df 100644 --- a/skeleton/scaffold-navigation/src/main.ext +++ b/skeleton/scaffold-navigation/src/main.ext @@ -7,7 +7,7 @@ import 'bootstrap'; // @if feat.typescript import {Aurelia} from 'aurelia-framework'; // @endif -import environment from './environment'; +import * as environment from '../config/environment.json'; // @if feat.webpack import {PLATFORM} from 'aurelia-pal'; // @endif diff --git a/skeleton/webpack/README.md b/skeleton/webpack/README.md index ba3ea9c6a..118f9f347 100644 --- a/skeleton/webpack/README.md +++ b/skeleton/webpack/README.md @@ -2,16 +2,14 @@ For more information, go to https://aurelia.io/docs/cli/webpack ## Run dev app -Run `au run`, then open `http://localhost:/* @if feat.web */8080/* @endif *//* @if feat['dotnet-core'] */5000/* @endif */` +Run `npm start`, then open `http://localhost:/* @if feat.web */8080/* @endif *//* @if feat['dotnet-core'] */5000/* @endif */` -To open browser automatically, do `au run --open`. +You can change the standard webpack configurations from CLI easily with something like this: `npm start -- --open --port 8888`. However, it is better to change the respective npm scripts or `webpack.config.js` with these options, as per your need. -To change dev server port, do `au run --port 8888`. +To enable Webpack Bundle Analyzer, do `npm run analyze` (production build). -To enable Webpack Bundle Analyzer, do `au run --analyze`. - -To enable hot module reload, do `au run --hmr`. +To enable hot module reload, do `npm start -- --env.hmr`. ## Build for production -Run `au build --env prod`. +Run `npm run build`. diff --git a/skeleton/webpack/aurelia_project/tasks/build.ext b/skeleton/webpack/aurelia_project/tasks/build.ext deleted file mode 100644 index e386af35a..000000000 --- a/skeleton/webpack/aurelia_project/tasks/build.ext +++ /dev/null @@ -1,67 +0,0 @@ -// @if feat.babel -import webpackConfig from '../../webpack.config'; -import webpack from 'webpack'; -import project from '../aurelia.json'; -import gulp from 'gulp'; -import del from 'del'; -// @endif -// @if feat.typescript -import * as webpackConfig from '../../webpack.config'; -import * as webpack from 'webpack'; -import * as project from '../aurelia.json'; -import * as gulp from 'gulp'; -import * as del from 'del'; -// @endif -import {CLIOptions, Configuration} from 'aurelia-cli'; -import configureEnvironment from './environment'; - -const analyze = CLIOptions.hasFlag('analyze'); -const buildOptions = new Configuration(project.build.options); -const production = CLIOptions.getEnvironment() === 'prod'; -const server = buildOptions.isApplicable('server'); -const extractCss = buildOptions.isApplicable('extractCss'); -const coverage = buildOptions.isApplicable('coverage'); - -const config = webpackConfig({ - production, server, extractCss, coverage, analyze -}); -const compiler = webpack(/* @if feat.typescript **/* @endif */config); - -function buildWebpack(done) { - if (CLIOptions.hasFlag('watch')) { - compiler.watch({}, onBuild); - } else { - compiler.run(onBuild); - compiler.hooks.done.tap('done', () => done()); - } -} - -function onBuild(err, stats) { - if (!CLIOptions.hasFlag('watch') && err) { - console.error(err.stack || err); - if (err.details) console.error(err.details); - process.exit(1); - } else { - process.stdout.write(stats.toString({ colors: require('supports-color') }) + '\n'); - - if (!CLIOptions.hasFlag('watch') && stats.hasErrors()) { - process.exit(1); - } - } -} - -function clearDist() { - return del([config.output.path]); -} - -const build = gulp.series( - clearDist, - configureEnvironment, - buildWebpack -); - -export { - config, - buildWebpack, - build as default -}; diff --git a/skeleton/webpack/aurelia_project/tasks/build.json b/skeleton/webpack/aurelia_project/tasks/build.json deleted file mode 100644 index 27a093605..000000000 --- a/skeleton/webpack/aurelia_project/tasks/build.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "build", - "description": "Builds and processes all application assets.", - "flags": [ - { - "name": "analyze", - "description": "Enable Webpack Bundle Analyzer. Typically paired with --env prod", - "type": "boolean" - }, - { - "name": "env", - "description": "Sets the build environment.", - "type": "string" - }, - { - "name": "watch", - "description": "Watches source files for changes and refreshes the bundles automatically.", - "type": "boolean" - } - ] -} diff --git a/skeleton/webpack/aurelia_project/tasks/run.ext b/skeleton/webpack/aurelia_project/tasks/run.ext deleted file mode 100644 index 003fea0a1..000000000 --- a/skeleton/webpack/aurelia_project/tasks/run.ext +++ /dev/null @@ -1,62 +0,0 @@ -// @if feat.babel -import webpack from 'webpack'; -import Server from 'webpack-dev-server'; -import project from '../aurelia.json'; -import gulp from 'gulp'; -// @endif -// @if feat.typescript -import * as webpack from 'webpack'; -import * as Server from 'webpack-dev-server'; -import * as project from '../aurelia.json'; -import * as gulp from 'gulp'; -// @endif - -import {config} from './build'; -import configureEnvironment from './environment'; -import {CLIOptions, reportWebpackReadiness} from 'aurelia-cli'; - -function runWebpack(done) { - // https://webpack.github.io/docs/webpack-dev-server.html - let opts = { - host: 'localhost', - publicPath: config.output.publicPath, - filename: config.output.filename, - hot: project.platform.hmr || CLIOptions.hasFlag('hmr'), - port: CLIOptions.getFlagValue('port') || project.platform.port, - contentBase: config.output.path, - historyApiFallback: true, - open: project.platform.open || CLIOptions.hasFlag('open'), - stats: { - colors: require('supports-color') - }, - ...config.devServer - }/* @if feat.typescript ** as any/* @endif */; - - // Add the webpack-dev-server client to the webpack entry point - // The path for the client to use such as `webpack-dev-server/client?http://${opts.host}:${opts.port}/` is not required - // The path used is derived from window.location in the browser and output.publicPath in the webpack.config. - if (project.platform.hmr || CLIOptions.hasFlag('hmr')) { - config.plugins.push(new webpack.HotModuleReplacementPlugin()); - config.entry.app.unshift('webpack-dev-server/client', 'webpack/hot/dev-server'); - } else { - // removed "" from index.ejs in favour of this method - config.entry.app.unshift('webpack-dev-server/client'); - } - - const compiler = webpack(config); - let server = new Server(compiler, opts); - - server.listen(opts.port, opts.host, function(err) { - if (err) throw err; - - reportWebpackReadiness(opts); - done(); - }); -} - -const run = gulp.series( - configureEnvironment, - runWebpack -); - -export { run as default }; diff --git a/skeleton/webpack/aurelia_project/tasks/run.json b/skeleton/webpack/aurelia_project/tasks/run.json deleted file mode 100644 index 99b409d69..000000000 --- a/skeleton/webpack/aurelia_project/tasks/run.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "run", - "description": "Builds the application and serves up the assets via a local web server, watching files for changes as you work.", - "flags": [ - { - "name": "analyze", - "description": "Enable Webpack Bundle Analyzer. Typically paired with --env prod", - "type": "boolean" - }, - { - "name": "env", - "description": "Sets the build environment.", - "type": "string" - }, - { - "name": "hmr", - "description": "Enable Hot Module Reload", - "type": "boolean" - }, - { - "name": "port", - "description": "Set port number of the dev server", - "type": "string" - }, - { - "name": "open", - "description": "Open the default browser at the application location.", - "type": "boolean" - } - ] -} diff --git a/skeleton/webpack/gulpFile.js b/skeleton/webpack/gulpFile.js new file mode 100644 index 000000000..5dfeb25ed --- /dev/null +++ b/skeleton/webpack/gulpFile.js @@ -0,0 +1,10 @@ +const del = require('del'); +const gulp = require('gulp'); +const path = require('path'); +const project = require('./aurelia_project/aurelia.json'); + +function clearDist() { + return del([path.resolve(__dirname, project.platform.output)]); +} + +gulp.task("prebuild", clearDist); \ No newline at end of file diff --git a/skeleton/webpack/package.json b/skeleton/webpack/package.json index a9e7c1796..6b687531a 100644 --- a/skeleton/webpack/package.json +++ b/skeleton/webpack/package.json @@ -64,10 +64,23 @@ "del": "", "css-loader": "", "file-loader": "", + "app-settings-loader": "", "json-loader": "", "html-loader": "", "istanbul-instrumenter-loader": "", "opn": "", "webpack-bundle-analyzer": "", + }, + "scripts": { + "build": "gulp prebuild && webpack --env.production --env.extractCss", + "build:dev": "gulp prebuild && webpack --env.extractCss", + "analyze": "webpack --env.production --env.analyze", + // @if feat['dotnet-core'] + "start": "gulp prebuild && webpack-dev-server --env.extractCss --port 5000" + // @endif + + // @if feat.web + "start": "gulp prebuild && webpack-dev-server --env.extractCss --port 8080" + // @endif } } \ No newline at end of file diff --git a/skeleton/webpack/webpack.config.js b/skeleton/webpack/webpack.config.js index dd9616244..a0e0dd783 100644 --- a/skeleton/webpack/webpack.config.js +++ b/skeleton/webpack/webpack.config.js @@ -50,7 +50,7 @@ const sassRules = [ ]; // @endif -module.exports = ({ production, server, extractCss, coverage, analyze, karma } = {}) => ({ +module.exports = ({ production, extractCss, analyze, tests, hmr } = {}) => ({ resolve: { // @if feat.typescript extensions: ['.ts', '.js'], @@ -206,7 +206,8 @@ module.exports = ({ production, server, extractCss, coverage, analyze, karma } = devServer: { contentBase: outDir, // serve index.html for all 404 (required for push-state) - historyApiFallback: true + historyApiFallback: true, + hot: hmr }, devtool: production ? 'nosources-source-map' : 'cheap-module-eval-source-map', module: { @@ -278,11 +279,11 @@ module.exports = ({ production, server, extractCss, coverage, analyze, karma } = // @if feat.babel { test: /\.js$/i, loader: 'babel-loader', exclude: nodeModulesDir, - options: coverage ? { sourceMap: 'inline', plugins: ['istanbul'] } : {} + options: tests ? { sourceMap: 'inline', plugins: ['istanbul'] } : {} }, // @endif // @if feat.typescript - { test: /\.ts$/, loader: "ts-loader", options: { reportFiles: [ srcDir+'/**/*.ts'] }, include: srcDir }, + { test: /\.ts$/, loader: "ts-loader" }, // @endif // embed small images and fonts as Data Urls and larger ones as files: { test: /\.(png|gif|jpg|cur)$/i, loader: 'url-loader', options: { limit: 8192 } }, @@ -290,8 +291,11 @@ module.exports = ({ production, server, extractCss, coverage, analyze, karma } = { test: /\.woff(\?v=[0-9]\.[0-9]\.[0-9])?$/i, loader: 'url-loader', options: { limit: 10000, mimetype: 'application/font-woff' } }, // load these fonts normally, as files: { test: /\.(ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/i, loader: 'file-loader' }, + { test: /environment\.json$/i, use: [ + {loader: "app-settings-loader", options: {env: production ? 'production' : 'development' }}, + ]}, // @if feat.typescript - ...when(coverage, { + ...when(tests, { test: /\.[jt]s$/i, loader: 'istanbul-instrumenter-loader', include: srcDir, exclude: [/\.(spec|test)\.[jt]s$/i], enforce: 'post', options: { esModules: true }, @@ -300,7 +304,7 @@ module.exports = ({ production, server, extractCss, coverage, analyze, karma } = ] }, plugins: [ - ...when(!karma, new DuplicatePackageCheckerPlugin()), + ...when(!tests, new DuplicatePackageCheckerPlugin()), new AureliaPlugin(), new ProvidePlugin({ // @if feat['scaffold-navigation'] @@ -336,7 +340,7 @@ module.exports = ({ production, server, extractCss, coverage, analyze, karma } = // @endif metadata: { // available in index.ejs // - title, server, baseUrl + title, baseUrl } }), // ref: https://webpack.js.org/plugins/mini-css-extract-plugin/ @@ -344,7 +348,7 @@ module.exports = ({ production, server, extractCss, coverage, analyze, karma } = filename: production ? 'css/[name].[contenthash].bundle.css' : 'css/[name].[hash].bundle.css', chunkFilename: production ? 'css/[name].[contenthash].chunk.css' : 'css/[name].[hash].chunk.css' })), - ...when(production || server, new CopyWebpackPlugin([ + ...when(!tests, new CopyWebpackPlugin([ { from: 'static', to: outDir, ignore: ['.*'] }])), // ignore dot (hidden) files ...when(analyze, new BundleAnalyzerPlugin()) ]