angular-cli: less-loader break change and cause error in @angular/cli 6.0

Versions

Angular CLI: 6.0.0
Node: 8.10.0
OS: darwin x64
Angular: 5.2.9
... animations, common, compiler, core, forms, http
... platform-browser, platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.5.7
@angular-devkit/build-angular     0.5.7
@angular-devkit/build-optimizer   0.5.7
@angular-devkit/core              0.5.7
@angular-devkit/schematics        0.5.7
@angular/cdk                      5.2.4
@angular/cli                      6.0.0-rc.5
@angular/compiler-cli             5.2.10
@angular/language-service         5.2.10
@ngtools/json-schema              1.1.0
@ngtools/webpack                  6.0.0-rc.5
@schematics/angular               0.5.7
@schematics/update                0.5.7
rxjs                              5.5.2
typescript                        2.4.2
webpack                           4.5.0

Repro steps

  • Step 1 install @angular/cli 6.0 version

  • Step 2 run ng new next-cli --style=less

  • Step 3 copy the follow less code and paste it into style.less

.bezierEasingMixin() {
  @functions: ~`(function() {
  var NEWTON_ITERATIONS = 4;
  var NEWTON_MIN_SLOPE = 0.001;
  var SUBDIVISION_PRECISION = 0.0000001;
  var SUBDIVISION_MAX_ITERATIONS = 10;

  var kSplineTableSize = 11;
  var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);

  var float32ArraySupported = typeof Float32Array === 'function';

  function A (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
  function B (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
  function C (aA1)      { return 3.0 * aA1; }

  // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
  function calcBezier (aT, aA1, aA2) { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; }

  // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
  function getSlope (aT, aA1, aA2) { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); }

  function binarySubdivide (aX, aA, aB, mX1, mX2) {
    var currentX, currentT, i = 0;
    do {
      currentT = aA + (aB - aA) / 2.0;
      currentX = calcBezier(currentT, mX1, mX2) - aX;
      if (currentX > 0.0) {
        aB = currentT;
      } else {
        aA = currentT;
      }
    } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
    return currentT;
  }

  function newtonRaphsonIterate (aX, aGuessT, mX1, mX2) {
   for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
     var currentSlope = getSlope(aGuessT, mX1, mX2);
     if (currentSlope === 0.0) {
       return aGuessT;
     }
     var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
     aGuessT -= currentX / currentSlope;
   }
   return aGuessT;
  }

  var BezierEasing = function (mX1, mY1, mX2, mY2) {
    if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) {
      throw new Error('bezier x values must be in [0, 1] range');
    }

    // Precompute samples table
    var sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
    if (mX1 !== mY1 || mX2 !== mY2) {
      for (var i = 0; i < kSplineTableSize; ++i) {
        sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
      }
    }

    function getTForX (aX) {
      var intervalStart = 0.0;
      var currentSample = 1;
      var lastSample = kSplineTableSize - 1;

      for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
        intervalStart += kSampleStepSize;
      }
      --currentSample;

      // Interpolate to provide an initial guess for t
      var dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
      var guessForT = intervalStart + dist * kSampleStepSize;

      var initialSlope = getSlope(guessForT, mX1, mX2);
      if (initialSlope >= NEWTON_MIN_SLOPE) {
        return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
      } else if (initialSlope === 0.0) {
        return guessForT;
      } else {
        return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
      }
    }

    return function BezierEasing (x) {
      if (mX1 === mY1 && mX2 === mY2) {
        return x; // linear
      }
      // Because JavaScript number are imprecise, we should guarantee the extremes are right.
      if (x === 0) {
        return 0;
      }
      if (x === 1) {
        return 1;
      }
      return calcBezier(getTForX(x), mY1, mY2);
    };
  };

  this.colorEasing = BezierEasing(0.26, 0.09, 0.37, 0.18);
  // less 3 requires a return
  return '';
})()`;
}
// It is hacky way to make this function will be compiled preferentially by less
// resolve error: `ReferenceError: colorPalette is not defined`
.bezierEasingMixin();

  • Step 4 run ng serve

Observed behavior

the less inline javascript works error in @angular/cli 6.0 version

Inline JavaScript is not enabled. Is it set in your options?
      in /Users/Documents/next-cli/src/styles.less (line 110, column 0)

it works well in @angular/cli 1.x version

Desired behavior

make less-loader work fine as before in 6.0 version or provide configuration to set less options in angular.json

Mention any other details that might be useful (optional)

add { javascriptEnabled: true } here can make it works again.

https://github.com/angular/devkit/blob/3d809ef29cf690f9d2b37fa048710132a7a9e389/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/styles.ts#L203

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 25
  • Comments: 16 (5 by maintainers)

Commits related to this issue

Most upvoted comments

Hi @filipesilva , any update on this issue? it still not work on latest version of angular-cli thanks.

Just ran into the same thing. This is a blocker for our upgrade to Angular 6.

npm install less@2.7.1 -g
lessc node_modules/ng-zorro-antd/src/ng-zorro-antd.less ./src/styles.css

@clydin yes, but the angular cli does not provide config for less-loader yet, it will block users to upgrade to it since less file will no longer work now.

@vthinkxie I see how that is problematic on your side. Let me reopen to discuss further. Will bring it up with the team.

According the the less.js documentation, inline javascript support has been deprecated and disabled by default due to the potential for security issues. The recommended approach is to now use the @plugin at-rule described here: http://lesscss.org/features/#plugin-atrules-feature

@filipesilva yes, the @plugin works well, but all the ant design (https://github.com/ant-design/ant-design) design system are based on javascript in less (which more than 10,000 lines of less code and can not be changed into @plugin right away). The react version of ant design can work with less option in webpack configuration file, but in angular version which most users work with @angular/cli, we can do noting with less configuration.

We can not change less file since we must sync it with react version, and we can not config less config because @angular/cli does not provide it now. Thanks for your response any way.