Skip to content

Commit

Permalink
feat(build): add support for custom baseHref and deployUrl in angular…
Browse files Browse the repository at this point in the history
…-cli.json file with BaseHrefWebpackPlugin

ISSUES CLOSED: #148
  • Loading branch information
christophercr committed May 16, 2018
1 parent 33c701e commit cf941bd
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 68 deletions.
125 changes: 121 additions & 4 deletions packages/stark-build/config/webpack.common-data.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,146 @@
"use strict";

const path = require("path");

// The goal of this module is only to export common configuration data that the different Webpack configuration files use

const { PostcssCliResources } = require("@angular/cli/plugins/webpack");

// Helpers
const helpers = require("./helpers");
const buildUtils = require("./build-utils");

// Metadata
const starkAppMetadata = require(helpers.root("src/stark-app-metadata.json"));
const starkAppConfig = require(helpers.root("src/stark-app-config.json"));

// Angular CLI config
const angularCliAppConfig = buildUtils.getAngularCliAppConfig();
const deployUrl = angularCliAppConfig.deployUrl;
const baseHref = angularCliAppConfig.baseHref;
// Maximum resource size to inline (KiB) (as defined in node_modules/@angular/cli/models/webpack-configs/styles.js)
const maximumInlineSize = 10;

// PostCSS Plugins
const postcssPlugins = [
const postcssPlugins = loader => [
// reference: https://github.com/postcss/postcss-import
// https://github.com/postcss/postcss-import/issues/244
require("postcss-import")(),
require("postcss-import")(
// configuration taken as is from node_modules/@angular/cli/models/webpack-configs/styles.js
{
resolve: (url, context) => {
return new Promise((resolve, reject) => {
let hadTilde = false;
if (url && url.startsWith("~")) {
url = url.substr(1);
hadTilde = true;
}
loader.resolve(context, (hadTilde ? "" : "./") + url, (err, result) => {
if (err) {
if (hadTilde) {
reject(err);
return;
}
loader.resolve(context, url, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
} else {
resolve(result);
}
});
});
},
load: filename => {
return new Promise((resolve, reject) => {
loader.fs.readFile(filename, (err, data) => {
if (err) {
reject(err);
return;
}
const content = data.toString();
resolve(content);
});
});
}
}
),

// plugin to rebase, inline or copy on url().
// https://github.com/postcss/postcss-url
require("postcss-url")(),
require("postcss-url")(
// configuration taken as is from node_modules/@angular/cli/models/webpack-configs/styles.js
{
filter: ({ url }) => url.startsWith("~"),
url: ({ url }) => {
const fullPath = helpers.root("node_modules", url.substr(1));
return path.relative(loader.context, fullPath).replace(/\\/g, "/");
}
}
),
require("postcss-url")(
// configuration taken as is from node_modules/@angular/cli/models/webpack-configs/styles.js
[
{
// Only convert root relative URLs, which CSS-Loader won't process into require().
filter: ({ url }) => url.startsWith("/") && !url.startsWith("//"),
url: ({ url }) => {
if (deployUrl.match(/:\/\//) || deployUrl.startsWith("/")) {
// If deployUrl is absolute or root relative, ignore baseHref & use deployUrl as is.
return `${deployUrl.replace(/\/$/, "")}${url}`;
} else if (baseHref.match(/:\/\//)) {
// If baseHref contains a scheme, include it as is.
return baseHref.replace(/\/$/, "") + `/${deployUrl}/${url}`.replace(/\/\/+/g, "/");
} else {
// Join together base-href, deploy-url and the original URL.
// Also dedupe multiple slashes into single ones.
return `/${baseHref}/${deployUrl}/${url}`.replace(/\/\/+/g, "/");
}
}
},
{
// TODO: inline .cur if not supporting IE (use browserslist to check)
filter: asset => {
return maximumInlineSize > 0 && !asset.hash && !asset.absolutePath.endsWith(".cur");
},
url: "inline",
// NOTE: maxSize is in KB
maxSize: maximumInlineSize,
fallback: "rebase"
},
{ url: "rebase" }
]
),

// plugin that lets nest style rules inside each other
// https://github.com/jonathantneal/postcss-nesting
require("postcss-nesting")(),

// plugin for extending placeholder selectors
// https://github.com/davidtheclark/postcss-simple-extend
require("postcss-simple-extend")(),

// plugin that allows to use the latest CSS syntax transforming it into cross-browser compatible CSS
// https://github.com/MoOx/postcss-cssnext
require("postcss-cssnext")({
// also adds vendor prefixes automatically using "autoprefixer"
// this plugin should be included in the right order
// see https://github.com/MoOx/postcss-cssnext/issues/268 for example
browsers: ["last 3 versions", "Chrome >= 45"]
browsers: ["last 3 versions", "Chrome >= 56"]
}),

// configuration taken as is from node_modules/@angular/cli/models/webpack-configs/styles.js
// the hashing format is just [hash] instead of the ones defined in node_modules/@angular/cli/models/webpack-config.js:
//
// import { getOutputHashFormat } from '@angular/cli/models/webpack-configs/utils';
// const hashFormat = getOutputHashFormat("all"); // "media" => development, "all" production
PostcssCliResources({
deployUrl: loader.loaders[loader.loaderIndex].options.ident === "extracted" ? "" : deployUrl,
loader,
filename: `[name].[hash].[ext]`
})
];

Expand Down
15 changes: 13 additions & 2 deletions packages/stark-build/config/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const commonData = require("./webpack.common-data.js"); // common configuration
const CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const BaseHrefWebpackPlugin = require("base-href-webpack-plugin").BaseHrefWebpackPlugin;
// const InlineManifestWebpackPlugin = require("inline-manifest-webpack-plugin");
// const ScriptExtHtmlWebpackPlugin = require("script-ext-html-webpack-plugin");
const { AngularCompilerPlugin } = require("@ngtools/webpack");
Expand Down Expand Up @@ -66,7 +67,8 @@ module.exports = function(options) {
}
};

const rootDir = buildUtils.getAngularCliAppConfig().root;
const angularCliAppConfig = buildUtils.getAngularCliAppConfig();
const rootDir = angularCliAppConfig.root;

return {
/**
Expand Down Expand Up @@ -448,7 +450,7 @@ module.exports = function(options) {
metadata: METADATA,
inject: "body", // true (default) or "body" are the same
starkAppMetadata: commonData.starkAppMetadata,
starkAppConfig: commonData.starkAppConfig,
starkAppConfig: commonData.starkAppConfig, // TODO: shall we remove it?
// xhtml: true, // TODO: why XHTML?
minify: isProd
? {
Expand All @@ -459,6 +461,15 @@ module.exports = function(options) {
: false
}),

/**
* Plugin: BaseHrefWebpackPlugin
* Description: Extension for html-webpack-plugin to programmatically insert or update <base href="" /> tag.
* Therefore, HtmlWebpackPlugin should also be installed
*
* See: https://github.com/dzonatan/base-href-webpack-plugin
*/
new BaseHrefWebpackPlugin({ baseHref: angularCliAppConfig.baseHref }),

/**
* Plugin: ScriptExtHtmlWebpackPlugin
* Description: Enhances html-webpack-plugin functionality
Expand Down
68 changes: 40 additions & 28 deletions packages/stark-build/config/webpack.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ const WebpackMonitor = require("webpack-monitor");
/**
* Webpack configuration
*
* See: http://webpack.github.io/docs/configuration.html#cli
* See: https://webpack.js.org/configuration/
*/
module.exports = function (env) {
module.exports = function(env) {
// for the content of the env parameter see here : https://webpack.js.org/api/cli/#environment-options
const ENV = (process.env.ENV = process.env.NODE_ENV = "development");
const HOST = process.env.HOST || "localhost";
Expand All @@ -45,7 +45,7 @@ module.exports = function (env) {
// PUBLIC: process.env.PUBLIC_DEV || HOST + ':' + PORT // TODO check if needed/useful in our case?
});

// Directives to be used in CSP header
// Directives to be used in CSP header
const cspDirectives = [
"base-uri 'self'",
// "default-src 'self'", // FIXME: enable as soon as the issue is fixed in Angular (https://github.com/angular/angular-cli/issues/6872 )
Expand All @@ -63,9 +63,10 @@ module.exports = function (env) {
// "style-src 'self' 'nonce-uiroutervisualizer' 'nonce-cef324d21ec5483c8819cc7a5e33c4a2'" // we define the same nonce value as in the style-loader // FIXME: DomSharedStylesHost.prototype._addStylesToHost in platform-browser.js adds inline style!
];

const rootDir = buildUtils.getAngularCliAppConfig().root;
const angularCliAppConfig = buildUtils.getAngularCliAppConfig();
const rootDir = angularCliAppConfig.root;

return webpackMerge(commonConfig({ENV: ENV, metadata: METADATA}), {
return webpackMerge(commonConfig({ ENV: ENV, metadata: METADATA }), {
/**
* Tell webpack which environment the application is targeting.
* reference: https://webpack.js.org/configuration/target/
Expand All @@ -76,36 +77,45 @@ module.exports = function (env) {
/**
* Options affecting the output of the compilation.
*
* See: http://webpack.github.io/docs/configuration.html#output
* See: https://webpack.js.org/configuration/output/
*/
output: {
/**
* The output directory as absolute path (required).
*
* See: http://webpack.github.io/docs/configuration.html#output-path
* See: https://webpack.js.org/configuration/output/#output-path
*/
path: helpers.root(buildUtils.getAngularCliAppConfig().outDir),
path: helpers.root(angularCliAppConfig.outDir),

/**
* This option specifies the public URL of the output directory when referenced in a browser.
* The value of the option is prefixed to every URL created by the runtime or loaders.
* Because of this the value of this option ends with / in most cases.
*
* See: https://webpack.js.org/configuration/output/#output-publicpath
*/
publicPath: angularCliAppConfig.deployUrl,

/**
* Specifies the name of each output file on disk.
* IMPORTANT: You must not specify an absolute path here!
*
* See: http://webpack.github.io/docs/configuration.html#output-filename
* See: https://webpack.js.org/configuration/output/#output-filename
*/
filename: "[name].[hash].bundle.js",

/**
* The filename of the SourceMaps for the JavaScript files.
* They are inside the output.path directory.
*
* See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
* See: https://webpack.js.org/configuration/output/#output-sourcemapfilename
*/
sourceMapFilename: "[file].[hash].map",

/** The filename of non-entry chunks as relative path
* inside the output.path directory.
*
* See: http://webpack.github.io/docs/configuration.html#output-chunkfilename
* See: https://webpack.js.org/configuration/output/#output-chunkfilename
*/
chunkFilename: "[id].[hash].chunk.js",

Expand All @@ -122,10 +132,13 @@ module.exports = function (env) {
*/
{
test: /\.css$/,
use: [{
loader: "style-loader",
options: {attrs: {nonce: "cef324d21ec5483c8819cc7a5e33c4a2"}}
}, "css-loader"],
use: [
{
loader: "style-loader",
options: { attrs: { nonce: "cef324d21ec5483c8819cc7a5e33c4a2" } }
},
"css-loader"
],
include: [helpers.root(rootDir, "styles")]
},

Expand All @@ -137,7 +150,7 @@ module.exports = function (env) {
{
test: /\.scss$/,
use: [
{loader: "style-loader", options: {attrs: {nonce: "cef324d21ec5483c8819cc7a5e33c4a2"}}},
{ loader: "style-loader", options: { attrs: { nonce: "cef324d21ec5483c8819cc7a5e33c4a2" } } },
"css-loader",
"sass-loader"
],
Expand All @@ -152,7 +165,7 @@ module.exports = function (env) {
{
test: /\.pcss$/,
use: [
{loader: "style-loader", options: {attrs: {nonce: "cef324d21ec5483c8819cc7a5e33c4a2"}}},
{ loader: "style-loader", options: { attrs: { nonce: "cef324d21ec5483c8819cc7a5e33c4a2" } } },
{
loader: "css-loader",
options: {
Expand Down Expand Up @@ -240,14 +253,14 @@ module.exports = function (env) {
*/
...(MONITOR
? [
new WebpackMonitor({
capture: true, // -> default 'true'
target: helpers.root("reports/webpack-monitor/stats.json"), // default -> '../monitor/stats.json'
launch: true, // -> default 'false'
port: 3030, // default -> 8081
excludeSourceMaps: true // default 'true'
})
]
new WebpackMonitor({
capture: true, // -> default 'true'
target: helpers.root("reports/webpack-monitor/stats.json"), // default -> '../monitor/stats.json'
launch: true, // -> default 'false'
port: 3030, // default -> 8081
excludeSourceMaps: true // default 'true'
})
]
: [])
],

Expand Down Expand Up @@ -297,7 +310,7 @@ module.exports = function (env) {
*
* See: https://webpack.github.io/docs/webpack-dev-server.html
*/
before: function (app) {
before: function(app) {
// For example, to define custom handlers for some paths:
// app.get('/some/path', function(req, res) {
// res.json({ custom: 'response' });
Expand Down Expand Up @@ -331,5 +344,4 @@ module.exports = function (env) {
}
}
});
}
;
};
Loading

0 comments on commit cf941bd

Please sign in to comment.