build: speed-up stylesheet building (#12426)

* Switches back from `dart-sass` to `node-sass` due to a pretty huge slow-down we noticed (can be revisited)
* No longer copies all SCSS files to the temporary `package` output just in favor of the demo-app (slows down unnecessarily). This now allows us to live-reload theme changes within a second.
* No longer rebuilds all package SCSS files twice for the ES5 output (rel: https://github.com/angular/material2/pull/7403)
This commit is contained in:
Paul Gschwendtner
2018-07-31 18:06:39 +02:00
committed by Jeremy Elbourn
parent 08e6653707
commit e4ac04d678
9 changed files with 103 additions and 161 deletions
+20 -98
View File
@@ -6053,14 +6053,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -6075,20 +6073,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -6205,8 +6200,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"ini": {
"version": "1.3.5",
@@ -6218,7 +6212,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -6233,7 +6226,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -6241,14 +6233,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -6267,7 +6257,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -6348,8 +6337,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -6361,7 +6349,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@@ -6483,7 +6470,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -9092,74 +9078,6 @@
"through2": "^2.0.0"
}
},
"gulp-dart-sass": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/gulp-dart-sass/-/gulp-dart-sass-0.9.0.tgz",
"integrity": "sha512-WlWU9nm0ZIOedXDapeFPAIzAdb1I2ShsI/jve4WzXD4yvWy94kYm42wuD8sqPpe3TeixKzqKzg1YwesTPTU/UA==",
"dev": true,
"requires": {
"chalk": "^2.3.0",
"lodash.clonedeep": "^4.3.2",
"plugin-error": "^1.0.1",
"replace-ext": "^1.0.0",
"sass": "^1.3.2",
"strip-ansi": "^4.0.0",
"through2": "^2.0.0",
"vinyl-sourcemaps-apply": "^0.2.0"
},
"dependencies": {
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"chalk": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"dev": true,
"requires": {
"ansi-regex": "^3.0.0"
}
},
"supports-color": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"gulp-dom": {
"version": "0.9.17",
"resolved": "https://registry.npmjs.org/gulp-dom/-/gulp-dom-0.9.17.tgz",
@@ -9507,6 +9425,19 @@
"integrity": "sha512-nEuZB7/9i0IZ8AXORTizl2QLP9tcC9uWc/s329zElBLJw1CfOhmMXBxwVlCRKjDyrWuhVP0uBKl61KeQ32TiCg==",
"dev": true
},
"gulp-sass": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-3.2.1.tgz",
"integrity": "sha512-UATbRpSDsyXCnpYSPBUEvdvtSEzksJs7/oQ0CujIpzKqKrO6vlnYwhX2UTsGrf4rNLwqlSSaM271It0uHYvJ3Q==",
"dev": true,
"requires": {
"gulp-util": "^3.0",
"lodash.clonedeep": "^4.3.2",
"node-sass": "^4.8.3",
"through2": "^2.0.0",
"vinyl-sourcemaps-apply": "^0.2.0"
}
},
"gulp-transform": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/gulp-transform/-/gulp-transform-2.0.0.tgz",
@@ -16198,15 +16129,6 @@
}
}
},
"sass": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.10.1.tgz",
"integrity": "sha512-tmDf4uHAifn3WHydSn7BZY1Q39zdXdfjDlzYYgN/CuwwYWVVOBhFCKeF3QUdJNP9LvSXl6lSft0YRhYSRLc5dA==",
"dev": true,
"requires": {
"chokidar": "^2.0.0"
}
},
"sass-graph": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
+2 -2
View File
@@ -84,7 +84,6 @@
"gulp-cli": "^1.3.0",
"gulp-connect": "^5.0.0",
"gulp-conventional-changelog": "^1.1.3",
"gulp-dart-sass": "^0.9.0",
"gulp-dom": "^0.9.17",
"gulp-flatten": "^0.3.1",
"gulp-highlight-files": "^0.0.5",
@@ -92,6 +91,7 @@
"gulp-if": "^2.0.2",
"gulp-markdown": "^1.2.0",
"gulp-rename": "^1.2.2",
"gulp-sass": "^3.1.0",
"gulp-transform": "^2.0.0",
"gulp-util": "^3.0.8",
"hammerjs": "^2.0.8",
@@ -111,6 +111,7 @@
"minimatch": "^3.0.4",
"minimist": "^1.2.0",
"moment": "^2.18.1",
"node-sass": "^4.5.3",
"parse5": "^5.0.0",
"protractor": "^5.2.0",
"request": "^2.83.0",
@@ -119,7 +120,6 @@
"rollup-plugin-alias": "^1.4.0",
"rollup-plugin-node-resolve": "^3.0.3",
"run-sequence": "^1.2.2",
"sass": "^1.10.1",
"scss-bundle": "^2.0.1-beta.7",
"selenium-webdriver": "^3.6.0",
"sorcery": "^0.10.0",
+2 -1
View File
@@ -1,4 +1,5 @@
@import '../../dist/packages/material/core/theming/all-theme';
@import '../lib/core/theming/all-theme';
// Plus imports for other components in your app.
// Include the common styles for Angular Material. We include this here so that you only
+48 -29
View File
@@ -1,8 +1,8 @@
import {task} from 'gulp';
import {task, dest} from 'gulp';
import {tsBuildTask, copyTask, serverTask} from '../util/task_helpers';
import {join} from 'path';
import {
buildConfig, copyFiles, buildScssTask, sequenceTask, watchFiles
buildConfig, copyFiles, buildScssPipeline, sequenceTask, watchFiles
} from 'material2-build-tools';
import {
cdkPackage,
@@ -43,53 +43,35 @@ const vendorGlob = `+(${appVendors.join('|')})/**/*.+(html|css|js|map)`;
/** Glob that matches all assets that need to be copied to the output. */
const assetsGlob = join(appDir, `**/*.+(html|css|svg|ico)`);
task(':watch:devapp', () => {
watchFiles(join(appDir, '**/*.ts'), [':build:devapp:ts']);
watchFiles(join(appDir, '**/*.scss'), [':build:devapp:scss']);
watchFiles(join(appDir, '**/*.html'), [':build:devapp:assets']);
// Custom watchers for all packages that are used inside of the demo-app. This is necessary
// because we only want to build the changed package (using the build-no-bundles task).
watchFiles(join(cdkPackage.sourceDir, '**/*'), ['cdk:build-no-bundles']);
watchFiles(join(materialPackage.sourceDir, '**/!(*.scss)'), ['material:build-no-bundles']);
watchFiles(join(materialPackage.sourceDir, '**/*.scss'), [':build:devapp:material-with-styles']);
watchFiles(join(momentAdapterPackage.sourceDir, '**/*'),
['material-moment-adapter:build-no-bundles']);
watchFiles(join(materialExperimentalPackage.sourceDir, '**/*'),
['material-experimental:build-no-bundles']);
watchFiles(join(cdkExperimentalPackage.sourceDir, '**/*'),
['cdk-experimental:build-no-bundles']);
watchFiles(join(examplesPackage.sourceDir, '**/*'), ['material-examples:build-no-bundles']);
});
/** Path to the demo-app tsconfig file. */
const tsconfigPath = join(appDir, 'tsconfig-build.json');
task(':build:devapp:ts', tsBuildTask(tsconfigPath));
task(':build:devapp:scss', buildScssTask(outDir, appDir));
task(':build:devapp:assets', copyTask(assetsGlob, outDir));
task(':build:devapp:scss', () => buildScssPipeline(appDir).pipe(dest(outDir)));
task(':serve:devapp', serverTask(outDir, true));
// The themes for the demo-app are built by using the SCSS mixins from Material.
// Therefore when SCSS files have been changed, the custom theme needs to be rebuilt.
task(':build:devapp:material-with-styles', sequenceTask(
'material:build-no-bundles', ':build:devapp:scss'
));
task('build:devapp', sequenceTask(
'cdk:build-no-bundles',
'material:build-no-bundles',
'cdk-experimental:build-no-bundles',
'material-experimental:build-no-bundles',
'material-moment-adapter:build-no-bundles',
'build-examples-module', // The examples module needs to be built before building examples package
'build-examples-module',
// The examples module needs to be manually built before building examples package because
// when using the `no-bundles` task, the package-specific pre-build tasks won't be executed.
'material-examples:build-no-bundles',
[':build:devapp:assets', ':build:devapp:scss', ':build:devapp:ts']
));
task('serve:devapp', ['build:devapp'], sequenceTask([':serve:devapp', ':watch:devapp']));
/*
* Development App deployment tasks. These can be used to run the dev-app outside of our
* serve task with a middleware. e.g. on Firebase hosting.
*/
/** Task that copies all vendors into the demo-app package. Allows hosting the app on firebase. */
task('stage-deploy:devapp', ['build:devapp'], () => {
copyFiles(join(projectDir, 'node_modules'), vendorGlob, join(outDir, 'node_modules'));
@@ -118,3 +100,40 @@ task('deploy:devapp', ['stage-deploy:devapp'], () => {
.then(() => { console.log('Successfully deployed the demo-app to firebase'); process.exit(0); })
.catch((err: any) => { console.log(err); process.exit(1); });
});
/*
* Development app watch task. This task ensures that only the packages that have been affected
* by a file-change are being rebuilt. This speeds-up development and makes working on Material
* easier.
*/
task(':watch:devapp', () => {
watchFiles(join(appDir, '**/*.ts'), [':build:devapp:ts']);
watchFiles(join(appDir, '**/*.scss'), [':build:devapp:scss']);
watchFiles(join(appDir, '**/*.html'), [':build:devapp:assets']);
// Custom watchers for all packages that are used inside of the demo-app. This is necessary
// because we only want to build the changed package (using the build-no-bundles task).
// CDK package watchers.
watchFiles(join(cdkPackage.sourceDir, '**/*'), ['cdk:build-no-bundles']);
// Material package watchers.
watchFiles(join(materialPackage.sourceDir, '**/!(*-theme).scss'), ['material:build-no-bundles']);
watchFiles(join(materialPackage.sourceDir, '**/*-theme.scss'), [':build:devapp:scss']);
// Moment adapter package watchers
watchFiles(join(momentAdapterPackage.sourceDir, '**/*'),
['material-moment-adapter:build-no-bundles']);
// Material experimental package watchers
watchFiles(join(materialExperimentalPackage.sourceDir, '**/*'),
['material-experimental:build-no-bundles']);
// CDK experimental package watchers
watchFiles(join(cdkExperimentalPackage.sourceDir, '**/*'),
['cdk-experimental:build-no-bundles']);
// Example package watchers.
watchFiles(join(examplesPackage.sourceDir, '**/*'), ['material-examples:build-no-bundles']);
});
+8 -3
View File
@@ -19,14 +19,19 @@ const releasesDir = join(distDir, 'releases');
// Path to the release output of material.
const releasePath = join(releasesDir, 'material');
// The entry-point for the scss theming bundle.
const themingEntryPointPath = join(sourceDir, 'core', 'theming', '_all-theme.scss');
// Output path for the scss theming bundle.
const themingBundlePath = join(releasePath, '_theming.scss');
// Matches all pre-built theme css files
const prebuiltThemeGlob = join(outputDir, '**/theming/prebuilt/*.css?(.map)');
// Matches all SCSS files in the different packages.
const allScssGlob = join(buildConfig.packagesDir, '**/*.scss');
// Matches all SCSS files in the different packages. Note that this glob is not used to build
// the bundle. It's used to identify Sass files that shouldn't be included multiple times.
const allScssDedupeGlob = join(buildConfig.packagesDir, '**/*.scss');
// Pattern matching schematics files to be copied into the @angular/material package.
const schematicsGlobs = [
@@ -74,7 +79,7 @@ task('material:bundle-theming-scss', () => {
// Instantiates the SCSS bundler and bundles all imports of the specified entry point SCSS file.
// A glob of all SCSS files in the library will be passed to the bundler. The bundler takes an
// array of globs, which will match SCSS files that will be only included once in the bundle.
return new Bundler().Bundle(themingEntryPointPath, [allScssGlob]).then(result => {
return new Bundler().Bundle(themingEntryPointPath, [allScssDedupeGlob]).then(result => {
// The release directory is not created yet because the composing of the release happens when
// this task finishes.
mkdirpSync(releasePath);
@@ -0,0 +1,14 @@
import {src} from 'gulp';
import {join} from 'path';
// These imports lack of type definitions.
const gulpSass = require('gulp-sass');
const gulpIf = require('gulp-if');
const gulpCleanCss = require('gulp-clean-css');
/** Create a gulp task that builds SCSS files. */
export function buildScssPipeline(sourceDir: string, minifyOutput = false) {
return src(join(sourceDir, '**/*.scss'))
.pipe(gulpSass().on('error', gulpSass.logError))
.pipe(gulpIf(minifyOutput, gulpCleanCss()));
}
@@ -1,17 +0,0 @@
import {src, dest} from 'gulp';
import {join} from 'path';
// These imports lack of type definitions.
const gulpDartSass = require('gulp-dart-sass');
const gulpIf = require('gulp-if');
const gulpCleanCss = require('gulp-clean-css');
/** Create a gulp task that builds SCSS files. */
export function buildScssTask(outputDir: string, sourceDir: string, minifyOutput = false) {
return () => {
return src(join(sourceDir, '**/*.scss'))
.pipe(gulpDartSass.sync().on('error', gulpDartSass.logError))
.pipe(gulpIf(minifyOutput, gulpCleanCss()))
.pipe(dest(outputDir));
};
}
+8 -10
View File
@@ -2,12 +2,11 @@ import {dest, src, task} from 'gulp';
import {join} from 'path';
import {composeRelease} from '../build-release';
import {inlineResourcesForDirectory} from '../inline-resources';
import {buildScssTask} from './build-scss-task';
import {buildScssPipeline} from './build-scss-pipeline';
import {sequenceTask} from './sequence-task';
import {watchFiles} from './watch-files';
import {BuildPackage} from '../build-package';
// There are no type definitions available for these imports.
const htmlmin = require('gulp-htmlmin');
@@ -31,7 +30,7 @@ export function createPackageBuildTasks(buildPackage: BuildPackage, preBuildTask
const dependencyNames = buildPackage.dependencies.map(p => p.name);
// Glob that matches all style files that need to be copied to the package output.
const stylesGlob = join(buildPackage.sourceDir, '**/*.+(scss|css)');
const stylesGlob = join(buildPackage.sourceDir, '**/*.css');
// Glob that matches every HTML file in the current package.
const htmlGlob = join(buildPackage.sourceDir, '**/*.html');
@@ -90,17 +89,15 @@ export function createPackageBuildTasks(buildPackage: BuildPackage, preBuildTask
*/
task(`${taskName}:assets`, [
`${taskName}:assets:scss`,
`${taskName}:assets:es5-scss`,
`${taskName}:assets:copy-styles`,
`${taskName}:assets:html`
]);
task(`${taskName}:assets:scss`, buildScssTask(
buildPackage.outputDir, buildPackage.sourceDir, true)
);
task(`${taskName}:assets:es5-scss`, buildScssTask(
buildPackage.esm5OutputDir, buildPackage.sourceDir, true)
task(`${taskName}:assets:scss`, () => {
buildScssPipeline(buildPackage.sourceDir, true)
.pipe(dest(buildPackage.outputDir))
.pipe(dest(buildPackage.esm5OutputDir));
}
);
task(`${taskName}:assets:copy-styles`, () => {
@@ -108,6 +105,7 @@ export function createPackageBuildTasks(buildPackage: BuildPackage, preBuildTask
.pipe(dest(buildPackage.outputDir))
.pipe(dest(buildPackage.esm5OutputDir));
});
task(`${taskName}:assets:html`, () => {
return src(htmlGlob).pipe(htmlmin(htmlMinifierOptions))
.pipe(dest(buildPackage.outputDir))
+1 -1
View File
@@ -7,7 +7,7 @@ export * from './copy-files';
// Expose gulp utilities.
export * from './gulp/build-tasks-gulp';
export * from './gulp/build-scss-task';
export * from './gulp/build-scss-pipeline';
export * from './gulp/sequence-task';
export * from './gulp/trigger-livereload';
export * from './gulp/watch-files';