@angular-devkit/build-angular
Version:
Angular Webpack Build Facade
248 lines (247 loc) • 9.89 kB
JavaScript
;
/**
* @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
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStylesConfig = void 0;
const core_1 = require("@angular-devkit/core");
const fs = require("fs");
const path = require("path");
const plugins_1 = require("../plugins");
const helpers_1 = require("../utils/helpers");
// tslint:disable-next-line:no-big-function
function getStylesConfig(wco) {
var _a, _b, _c;
const autoprefixer = require('autoprefixer');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const postcssImports = require('postcss-import');
const { root, buildOptions } = wco;
const entryPoints = {};
const globalStylePaths = [];
const extraPlugins = [];
extraPlugins.push(new plugins_1.AnyComponentStyleBudgetChecker(buildOptions.budgets));
const cssSourceMap = buildOptions.sourceMap.styles;
// Determine hashing format.
const hashFormat = helpers_1.getOutputHashFormat(buildOptions.outputHashing);
// use includePaths from appConfig
const includePaths = (_c = (_b = (_a = buildOptions.stylePreprocessorOptions) === null || _a === void 0 ? void 0 : _a.includePaths) === null || _b === void 0 ? void 0 : _b.map(p => path.resolve(root, p))) !== null && _c !== void 0 ? _c : [];
// Process global styles.
if (buildOptions.styles.length > 0) {
const chunkNames = [];
helpers_1.normalizeExtraEntryPoints(buildOptions.styles, 'styles').forEach(style => {
let resolvedPath = path.resolve(root, style.input);
if (!fs.existsSync(resolvedPath)) {
try {
resolvedPath = require.resolve(style.input, { paths: [root] });
}
catch (_a) { }
}
// Add style entry points.
if (entryPoints[style.bundleName]) {
entryPoints[style.bundleName].push(resolvedPath);
}
else {
entryPoints[style.bundleName] = [resolvedPath];
}
// Add non injected styles to the list.
if (!style.inject) {
chunkNames.push(style.bundleName);
}
// Add global css paths.
globalStylePaths.push(resolvedPath);
});
if (chunkNames.length > 0) {
// Add plugin to remove hashes from lazy styles.
extraPlugins.push(new plugins_1.RemoveHashPlugin({ chunkNames, hashFormat }));
}
}
let sassImplementation;
try {
// tslint:disable-next-line:no-implicit-dependencies
sassImplementation = require('node-sass');
wco.logger.warn(core_1.tags.oneLine `'node-sass' usage is deprecated and will be removed in a future major version.
To opt-out of the deprecated behaviour and start using 'sass' uninstall 'node-sass'.`);
}
catch (_d) {
sassImplementation = require('sass');
}
// set base rules to derive final rules from
const baseRules = [
{ test: /\.css$/, use: [] },
{
test: /\.scss$|\.sass$/,
use: [
{
loader: require.resolve('resolve-url-loader'),
options: {
sourceMap: cssSourceMap,
},
},
{
loader: require.resolve('sass-loader'),
options: {
implementation: sassImplementation,
sourceMap: true,
sassOptions: {
// bootstrap-sass requires a minimum precision of 8
precision: 8,
includePaths,
// Use expanded as otherwise sass will remove comments that are needed for autoprefixer
// Ex: /* autoprefixer grid: autoplace */
// tslint:disable-next-line: max-line-length
// See: https://github.com/webpack-contrib/sass-loader/blob/45ad0be17264ceada5f0b4fb87e9357abe85c4ff/src/getSassOptions.js#L68-L70
outputStyle: 'expanded',
},
},
},
],
},
{
test: /\.less$/,
use: [
{
loader: require.resolve('less-loader'),
options: {
sourceMap: cssSourceMap,
lessOptions: {
javascriptEnabled: true,
paths: includePaths,
},
},
},
],
},
{
test: /\.styl$/,
use: [
{
loader: require.resolve('resolve-url-loader'),
options: {
sourceMap: cssSourceMap,
},
},
{
loader: require.resolve('stylus-loader'),
options: {
sourceMap: cssSourceMap,
webpackImporter: false,
stylusOptions: {
compress: false,
sourceMap: { comment: false },
paths: includePaths,
},
},
},
],
},
];
const postcssOptionsCreator = (sourceMap, extracted) => {
return (loader) => ({
map: sourceMap && {
inline: true,
annotation: false,
},
plugins: [
postcssImports({
resolve: (url) => url.startsWith('~') ? url.substr(1) : url,
load: (filename) => {
return new Promise((resolve, reject) => {
loader.fs.readFile(filename, (err, data) => {
if (err) {
reject(err);
return;
}
const content = data.toString();
resolve(content);
});
});
},
}),
plugins_1.PostcssCliResources({
baseHref: buildOptions.baseHref,
deployUrl: buildOptions.deployUrl,
resourcesOutputPath: buildOptions.resourcesOutputPath,
loader,
rebaseRootRelative: buildOptions.rebaseRootRelativeCssUrls,
filename: `[name]${hashFormat.file}.[ext]`,
emitFile: buildOptions.platform !== 'server',
extracted,
}),
autoprefixer(),
],
});
};
// load component css as raw strings
const componentsSourceMap = !!(cssSourceMap
// Never use component css sourcemap when style optimizations are on.
// It will just increase bundle size without offering good debug experience.
&& !buildOptions.optimization.styles
// Inline all sourcemap types except hidden ones, which are the same as no sourcemaps
// for component css.
&& !buildOptions.sourceMap.hidden);
const rules = baseRules.map(({ test, use }) => ({
exclude: globalStylePaths,
test,
use: [
{ loader: require.resolve('raw-loader') },
{
loader: require.resolve('postcss-loader'),
options: {
postcssOptions: postcssOptionsCreator(componentsSourceMap, false),
},
},
...use,
],
}));
// load global css as css files
if (globalStylePaths.length > 0) {
const globalSourceMap = !!(cssSourceMap && !buildOptions.extractCss && !buildOptions.sourceMap.hidden);
rules.push(...baseRules.map(({ test, use }) => {
return {
include: globalStylePaths,
test,
use: [
buildOptions.extractCss
? {
loader: MiniCssExtractPlugin.loader,
options: {
hmr: buildOptions.hmr,
},
}
: require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
url: false,
sourceMap: globalSourceMap,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
postcssOptions: postcssOptionsCreator(globalSourceMap, buildOptions.extractCss),
},
},
...use,
],
};
}));
}
if (buildOptions.extractCss) {
extraPlugins.push(
// extract global css from js files into own css file
new MiniCssExtractPlugin({ filename: `[name]${hashFormat.extract}.css` }),
// suppress empty .js files in css only entry points
new plugins_1.SuppressExtractedTextChunksWebpackPlugin());
}
return {
entry: entryPoints,
module: { rules },
plugins: extraPlugins,
};
}
exports.getStylesConfig = getStylesConfig;