From 888834570db3b751869b514bf0659ca678c9fe58 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Thu, 9 Apr 2020 19:45:47 +0200 Subject: [PATCH] fix(@angular-devkit/build-angular): retain css declarations order when using `extractCss` and `@import` rule Relevant code: https://github.com/webpack-contrib/css-loader/blob/239e43d1f3c88bce9433e49b9674be2192a118bb/src/plugins/postcss-import-parser.js#L9 https://github.com/webpack-contrib/css-loader/blob/239e43d1f3c88bce9433e49b9674be2192a118bb/src/index.js#L132-L150 Fixes #9475 --- .../angular_devkit/build_angular/package.json | 7 +- .../models/webpack-configs/styles.ts | 9 ++- .../plugins/raw-css-loader.ts | 14 ---- .../src/angular-cli-files/plugins/webpack.ts | 1 - .../test/browser/styles_spec_large.ts | 36 ++++++++++ yarn.lock | 65 ++++++++++++++++++- 6 files changed, 109 insertions(+), 23 deletions(-) delete mode 100644 packages/angular_devkit/build_angular/src/angular-cli-files/plugins/raw-css-loader.ts diff --git a/packages/angular_devkit/build_angular/package.json b/packages/angular_devkit/build_angular/package.json index 6522b11110c1..d7923ca4b660 100644 --- a/packages/angular_devkit/build_angular/package.json +++ b/packages/angular_devkit/build_angular/package.json @@ -26,6 +26,7 @@ "circular-dependency-plugin": "5.2.0", "copy-webpack-plugin": "5.1.1", "core-js": "3.6.4", + "css-loader": "3.5.1", "cssnano": "4.1.10", "file-loader": "6.0.0", "find-cache-dir": "3.3.1", @@ -53,15 +54,15 @@ "sass-loader": "8.0.2", "semver": "7.2.1", "source-map": "0.7.3", - "source-map-support": "0.5.16", "source-map-loader": "0.2.4", + "source-map-support": "0.5.16", "speed-measure-webpack-plugin": "1.3.3", "style-loader": "1.1.3", "stylus": "0.54.7", "stylus-loader": "3.0.2", - "tree-kill": "1.2.2", "terser": "4.6.11", "terser-webpack-plugin": "2.3.5", + "tree-kill": "1.2.2", "webpack": "4.42.1", "webpack-dev-middleware": "3.7.2", "webpack-dev-server": "3.10.3", @@ -89,9 +90,9 @@ "bootstrap": "^4.0.0", "codelyzer": "^5.0.0", "font-awesome": "^4.7.0", - "jquery": "^3.3.1", "jasmine-core": "~3.5.0", "jasmine-spec-reporter": "~4.2.1", + "jquery": "^3.3.1", "karma": "~4.4.1", "karma-chrome-launcher": "~3.1.0", "karma-coverage-istanbul-reporter": "~2.1.0", diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/styles.ts b/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/styles.ts index 3a84bed6f479..29964ea72936 100644 --- a/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/styles.ts +++ b/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/styles.ts @@ -11,7 +11,6 @@ import * as webpack from 'webpack'; import { AnyComponentStyleBudgetChecker, PostcssCliResources, - RawCssLoader, RemoveHashPlugin, SuppressExtractedTextChunksWebpackPlugin, } from '../../plugins/webpack'; @@ -206,7 +205,13 @@ export function getStylesConfig(wco: WebpackConfigOptions) { test, use: [ buildOptions.extractCss ? MiniCssExtractPlugin.loader : require.resolve('style-loader'), - RawCssLoader, + { + loader: require.resolve('css-loader'), + options: { + url: false, + sourceMap: cssSourceMap, + }, + }, { loader: require.resolve('postcss-loader'), options: { diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/raw-css-loader.ts b/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/raw-css-loader.ts deleted file mode 100644 index 9f7ff68b3032..000000000000 --- a/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/raw-css-loader.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -export default function(content: string, map: object) { - const stringifiedContent = JSON.stringify(content); - const stringifiedMap = map ? JSON.stringify(map) : `''`; - - return `module.exports = [[module.id, ${stringifiedContent}, '', ${stringifiedMap}]]`; -} diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/webpack.ts b/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/webpack.ts index 4a0b6127ffd9..664acbb5f250 100644 --- a/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/webpack.ts +++ b/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/webpack.ts @@ -21,5 +21,4 @@ export { } from './postcss-cli-resources'; import { join } from 'path'; -export const RawCssLoader = require.resolve(join(__dirname, 'raw-css-loader')); export const WebpackRollupLoader = require.resolve(join(__dirname, 'webpack-rollup-loader')); diff --git a/packages/angular_devkit/build_angular/test/browser/styles_spec_large.ts b/packages/angular_devkit/build_angular/test/browser/styles_spec_large.ts index 2926085fce5b..cd93214acf74 100644 --- a/packages/angular_devkit/build_angular/test/browser/styles_spec_large.ts +++ b/packages/angular_devkit/build_angular/test/browser/styles_spec_large.ts @@ -603,4 +603,40 @@ describe('Browser Builder styles', () => { const { output } = await browserBuild(architect, host, target, overrides); expect(output.success).toBe(true); }); + + extensionsWithImportSupport.forEach(ext => { + it(`retains declarations order in ${ext} files with extractCss when using @import`, async () => { + host.writeMultipleFiles({ + [`src/styles-one.${ext}`]: tags.stripIndents` + .one { + color: #fff; + } + `, + [`src/styles-two.${ext}`]: tags.stripIndents` + .two { + color: #fff; + } + `, + // LESS doesn't support css imports by default. + // See: https://github.com/less/less.js/issues/3188#issuecomment-374690630 + [`src/styles-three.${ext}`]: tags.stripIndents` + @import ${ext === 'less' ? ' (css) ' : ''}url("https://fonts.googleapis.com/css?family=Roboto:400"); + .three { + color: #fff; + } + `, + }); + + const overrides = { + extractCss: true, + styles: [ + `src/styles-one.${ext}`, + `src/styles-two.${ext}`, + `src/styles-three.${ext}`, + ], + }; + const { files } = await browserBuild(architect, host, target, overrides); + expect(await files['styles.css']).toMatch(/\.one(.|\n|\r)*\.two(.|\n|\r)*\.three/); + }); + }); }); diff --git a/yarn.lock b/yarn.lock index 26240149d001..d5607508d3ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3947,6 +3947,25 @@ css-declaration-sorter@^4.0.1: postcss "^7.0.1" timsort "^0.3.0" +css-loader@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.5.1.tgz#db2b2336f4169edb68e6a829ad4fd36552647b77" + integrity sha512-0G4CbcZzQ9D1Q6ndOfjFuMDo8uLYMu5vc9Abs5ztyHcKvmil6GJrMiNjzzi3tQvUF+mVRuDg7bE6Oc0Prolgig== + dependencies: + camelcase "^5.3.1" + cssesc "^3.0.0" + icss-utils "^4.1.1" + loader-utils "^1.2.3" + normalize-path "^3.0.0" + postcss "^7.0.27" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.2" + postcss-modules-scope "^2.2.0" + postcss-modules-values "^3.0.0" + postcss-value-parser "^4.0.3" + schema-utils "^2.6.5" + semver "^6.3.0" + css-parse@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4" @@ -6013,6 +6032,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: dependencies: safer-buffer ">= 2.1.2 < 3" +icss-utils@^4.0.0, icss-utils@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== + dependencies: + postcss "^7.0.14" + ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" @@ -9356,6 +9382,39 @@ postcss-minify-selectors@^4.0.2: postcss "^7.0.0" postcss-selector-parser "^3.0.0" +postcss-modules-extract-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== + dependencies: + postcss "^7.0.5" + +postcss-modules-local-by-default@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" + integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ== + dependencies: + icss-utils "^4.1.1" + postcss "^7.0.16" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.0" + +postcss-modules-scope@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" + +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== + dependencies: + icss-utils "^4.0.0" + postcss "^7.0.6" + postcss-normalize-charset@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" @@ -9475,7 +9534,7 @@ postcss-selector-parser@^3.0.0: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^6.0.2: +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== @@ -9519,12 +9578,12 @@ postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.2, postcss-value-parser@^4.0.3: +postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d" integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg== -"postcss@5 - 7", postcss@7.0.27, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.18, postcss@^7.0.2, postcss@^7.0.27: +"postcss@5 - 7", postcss@7.0.27, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.18, postcss@^7.0.2, postcss@^7.0.27, postcss@^7.0.5, postcss@^7.0.6: version "7.0.27" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9" integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==