Skip to content

Commit

Permalink
feat(build): add support for assets array (#2570)
Browse files Browse the repository at this point in the history
  • Loading branch information
filipesilva authored Oct 8, 2016
1 parent 1b46c11 commit de3c275
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 22 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
"chalk": "^1.1.3",
"common-tags": "^1.3.1",
"compression-webpack-plugin": "github:webpack/compression-webpack-plugin#7e55907cd54a2e91b96d25a660acc6a2a6453f54",
"copy-webpack-plugin": "^3.0.1",
"core-js": "^2.4.0",
"css-loader": "^0.23.1",
"denodeify": "^1.2.1",
Expand Down
Empty file.
5 changes: 4 additions & 1 deletion packages/angular-cli/blueprints/ng2/files/angular-cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
{
"root": "<%= sourceDir %>",
"outDir": "dist",
"assets": "assets",
"assets": [
"assets",
"favicon.ico"
],
"index": "index.html",
"main": "main.ts",
"test": "test.ts",
Expand Down
7 changes: 6 additions & 1 deletion packages/angular-cli/lib/config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@
"default": "dist/"
},
"assets": {
"type": "string"
"fixme": true,
"type": "array",
"items": {
"type": "string"
},
"default": []
},
"index": {
"type": "string",
Expand Down
6 changes: 6 additions & 0 deletions packages/angular-cli/models/json-schema/schema-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ export abstract class NonLeafSchemaTreeNode<T> extends SchemaTreeNode<T> {
// Helper function to create a child based on its schema.
protected _createChildProperty<T>(name: string, value: T, forward: SchemaTreeNode<T>,
schema: Schema, define = true): SchemaTreeNode<T> {

// TODO: fix this
if (schema['fixme'] && typeof value === 'string') {
value = <T>(<any>[ value ]);
}

const type = schema['type'];
let Klass: any = null;

Expand Down
12 changes: 5 additions & 7 deletions packages/angular-cli/models/webpack-build-common.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as webpack from 'webpack';
import * as path from 'path';
import {GlobCopyWebpackPlugin} from '../plugins/glob-copy-webpack-plugin';
import {BaseHrefWebpackPlugin} from '@angular-cli/base-href-webpack';

const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');


Expand Down Expand Up @@ -127,12 +127,10 @@ export function getWebpackCommonConfig(
filename: 'inline.js',
sourceMapFilename: 'inline.map'
}),
new CopyWebpackPlugin([{
context: path.resolve(appRoot, appConfig.assets),
from: { glob: '**/*', dot: true },
ignore: [ '.gitkeep' ],
to: path.resolve(projectRoot, appConfig.outDir, appConfig.assets)
}])
new GlobCopyWebpackPlugin({
patterns: appConfig.assets,
globOptions: {cwd: appRoot, dot: true, ignore: '**/.gitkeep'}
})
],
node: {
fs: 'empty',
Expand Down
15 changes: 5 additions & 10 deletions packages/angular-cli/models/webpack-build-mobile.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
import * as path from 'path';
const OfflinePlugin = require('offline-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
import { GlobCopyWebpackPlugin } from '../plugins/glob-copy-webpack-plugin';
import { PrerenderWebpackPlugin } from '../utilities/prerender-webpack-plugin';

export const getWebpackMobileConfigPartial = function (projectRoot: string, appConfig: any) {
// Hardcoded files and paths here should be part of appConfig when
// reworking the mobile app functionality
return {
plugins: [
new CopyWebpackPlugin([
{
from: path.resolve(projectRoot, appConfig.root, 'icons'),
to: path.resolve(projectRoot, appConfig.outDir, 'icons')
}, {
from: path.resolve(projectRoot, appConfig.root, 'manifest.webapp'),
to: path.resolve(projectRoot, appConfig.outDir)
}
]),
new GlobCopyWebpackPlugin({
patterns: [ 'icons', 'manifest.webapp'],
globOptions: {cwd: appConfig.root, dot: true, ignore: '**/.gitkeep'}
}),
new PrerenderWebpackPlugin({
templatePath: 'index.html',
configPath: path.resolve(projectRoot, appConfig.root, 'main-app-shell.ts'),
Expand Down
1 change: 0 additions & 1 deletion packages/angular-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
"chalk": "^1.1.3",
"common-tags": "^1.3.1",
"compression-webpack-plugin": "github:webpack/compression-webpack-plugin#7e55907cd54a2e91b96d25a660acc6a2a6453f54",
"copy-webpack-plugin": "^3.0.1",
"core-js": "^2.4.0",
"css-loader": "^0.23.1",
"denodeify": "^1.2.1",
Expand Down
51 changes: 51 additions & 0 deletions packages/angular-cli/plugins/glob-copy-webpack-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as fs from 'fs';
import * as path from 'path';
import * as glob from 'glob';
import * as denodeify from 'denodeify';

const globPromise = <any>denodeify(glob);
const statPromise = <any>denodeify(fs.stat);

export interface GlobCopyWebpackPluginOptions {
patterns: string[];
globOptions: any;
}

export class GlobCopyWebpackPlugin {
constructor(private options: GlobCopyWebpackPluginOptions) { }

apply(compiler: any): void {
let { patterns, globOptions } = this.options;
let context = globOptions.cwd || compiler.options.context;

// convert dir patterns to globs
patterns = patterns.map(pattern => fs.statSync(path.resolve(context, pattern)).isDirectory()
? pattern += '/**/*'
: pattern
);

// force nodir option, since we can't add dirs to assets
globOptions.nodir = true;

compiler.plugin('emit', (compilation: any, cb: any) => {
let globs = patterns.map(pattern => globPromise(pattern, globOptions));

let addAsset = (relPath: string) => compilation.assets[relPath]
// don't re-add to assets
? Promise.resolve()
: statPromise(path.resolve(context, relPath))
.then((stat: any) => compilation.assets[relPath] = {
size: () => stat.size,
source: () => fs.readFileSync(path.resolve(context, relPath))
});

Promise.all(globs)
// flatten results
.then(globResults => [].concat.apply([], globResults))
// add each file to compilation assets
.then(relPaths => relPaths.forEach((relPath: string) => addAsset(relPath)))
.catch((err) => compilation.errors.push(err))
.then(cb);
});
}
}
11 changes: 10 additions & 1 deletion tests/e2e/tests/misc/assets.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import {writeFile, expectFileToExist, expectFileToMatch} from '../../utils/fs';
import {ng} from '../../utils/process';
import {updateJsonFile} from '../../utils/project';
import {expectToFail} from '../../utils/utils';


export default function() {
return writeFile('src/assets/.file', '')
.then(() => writeFile('src/assets/test.abc', 'hello world'))
.then(() => ng('build'))
.then(() => expectFileToExist('dist/favicon.ico'))
.then(() => expectFileToExist('dist/assets/.file'))
.then(() => expectFileToMatch('dist/assets/test.abc', 'hello world'))
.then(() => expectToFail(() => expectFileToExist('dist/assets/.gitkeep')));
.then(() => expectToFail(() => expectFileToExist('dist/assets/.gitkeep')))
// doesn't break beta.16 projects
.then(() => updateJsonFile('angular-cli.json', configJson => {
const app = configJson['apps'][0];
app['assets'] = 'assets';
}))
.then(() => expectFileToExist('dist/assets/.file'))
.then(() => expectFileToMatch('dist/assets/test.abc', 'hello world'));
}

0 comments on commit de3c275

Please sign in to comment.