Skip to content

Commit

Permalink
feat(plugins): add rollup plugins through config
Browse files Browse the repository at this point in the history
Closes #472
  • Loading branch information
adamdbradley committed Feb 12, 2018
1 parent a8726be commit b8abbce
Show file tree
Hide file tree
Showing 11 changed files with 300 additions and 91 deletions.
3 changes: 2 additions & 1 deletion src/compiler/app/app-global-scripts.ts
Expand Up @@ -109,7 +109,8 @@ async function bundleProjectGlobal(config: Config, compilerCtx: CompilerCtx, bui
include: 'node_modules/**',
sourceMap: false
}),
transpiledInMemoryPlugin(config, compilerCtx)
transpiledInMemoryPlugin(config, compilerCtx),
...config.plugins
],
onwarn: createOnWarnFn(buildCtx.diagnostics)
});
Expand Down
1 change: 1 addition & 0 deletions src/compiler/bundle/rollup-bundle.ts
Expand Up @@ -35,6 +35,7 @@ export async function createBundle(config: Config, compilerCtx: CompilerCtx, bui
await pathsResolution(config, compilerCtx),
localResolution(config),
nodeEnvVars(config),
...config.plugins
],
onwarn: createOnWarnFn(buildCtx.diagnostics)
};
Expand Down
4 changes: 1 addition & 3 deletions src/compiler/compiler.ts
Expand Up @@ -3,22 +3,20 @@ import { build } from './build/build';
import { catchError, getCompilerCtx } from './util';
import { docs } from './docs/docs';
import { InMemoryFileSystem } from '../util/in-memory-fs';
import { initPlugins } from './plugin/plugin';
import { validateBuildConfig } from '../compiler/config/validate-config';
import { validatePrerenderConfig } from './prerender/validate-prerender-config';
import { validateServiceWorkerConfig } from './service-worker/validate-sw-config';


export class Compiler {
private ctx: CompilerCtx;
protected ctx: CompilerCtx;
isValid: boolean;

constructor(public config: Config) {
this.isValid = isValid(config);

if (this.isValid) {
this.ctx = getCompilerCtx(config);
initPlugins(config);

let startupMsg = `${config.sys.compiler.name} v${config.sys.compiler.version} `;
if (config.sys.platform !== 'win32') {
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/config/validate-config.ts
Expand Up @@ -4,6 +4,7 @@ import { validateCopy } from './validate-copy';
import { validateDependentCollection } from './validate-collection';
import { validateNamespace } from './validate-namespace';
import { validatePaths } from './validate-paths';
import { validatePlugins } from './validate-plugins';


export function validateBuildConfig(config: Config, setEnvVariables?: boolean) {
Expand Down Expand Up @@ -74,6 +75,8 @@ export function validateBuildConfig(config: Config, setEnvVariables?: boolean) {

validateCopy(config);

validatePlugins(config);

if (!config.watchIgnoredRegex) {
config.watchIgnoredRegex = DEFAULT_WATCH_IGNORED_REGEX;
}
Expand Down
16 changes: 16 additions & 0 deletions src/compiler/config/validate-plugins.ts
@@ -0,0 +1,16 @@
import { Config } from '../../declarations';
import styleMinifyPlugin from '../style/style-minify-plugin';
import styleSassPlugin from '../style/style-sass-plugin';


export function validatePlugins(config: Config) {
config.plugins = (config.plugins || []).filter(p => !!p);

if (!config.plugins.some(p => p.name === 'styleSassPlugin')) {
config.plugins.push(styleSassPlugin());
}

if (!config.plugins.some(p => p.name === 'styleMinifyPlugin')) {
config.plugins.push(styleMinifyPlugin());
}
}
13 changes: 0 additions & 13 deletions src/compiler/plugin/plugin.ts
@@ -1,19 +1,6 @@
import { BuildCtx, CompilerCtx, Config } from '../../declarations';
import { catchError } from '../util';
import { PluginCtx, PluginTransformResults } from '../../declarations/plugin';
import { StyleMinifyPlugin } from '../style/style-minify-plugin';
import { StyleSassPlugin } from '../style/style-sass-plugin';


export function initPlugins(config: Config) {
config.plugins = (config.plugins || []).filter(p => !!p);

const styleSassPlugin = new StyleSassPlugin();
config.plugins.push(styleSassPlugin);

const styleMinifyPlugin = new StyleMinifyPlugin();
config.plugins.push(styleMinifyPlugin);
}


export async function runPluginResolveId(pluginCtx: PluginCtx, importee: string) {
Expand Down
183 changes: 183 additions & 0 deletions src/compiler/plugin/test/plugin.spec.ts
@@ -0,0 +1,183 @@
import { TestingCompiler } from '../../../testing';
import { wroteFile } from '../../../testing/utils';
import * as path from 'path';
import * as ts from 'typescript';


describe('plugin', () => {
let c: TestingCompiler;

beforeEach(async () => {
c = new TestingCompiler();
await c.fs.writeFiles({'/src/index.html': `<cmp-a></cmp-a>`});
await c.fs.commit();
});

it('transform, async', async () => {
c.config.bundles = [ { components: ['cmp-a'] } ];

await c.fs.writeFiles({
'/stencil.config.js': `
function myPlugin() {
return {
transform: function(sourceText) {
return new Promise(resolve => {
resolve(sourceText.replace('constructor() { }', 'constructor(){console.log("transformed!")}'));
});
},
name: 'myPlugin'
};
}
exports.config = {
plugins: [myPlugin()]
};
`,
'/src/cmp-a.tsx': `
@Component({ tag: 'cmp-a' }) export class CmpA {
constructor() { }
}
`
}, { clearFileCache: true });
await c.fs.commit();

c.loadConfigFile('/stencil.config.js');

const r = await c.build();
expect(r.diagnostics).toEqual([]);

const cmpA = await c.fs.readFile('/www/build/app/cmp-a.js');
expect(cmpA).toContain('transformed!');
});

it('transform, sync', async () => {
c.config.bundles = [ { components: ['cmp-a'] } ];

await c.fs.writeFiles({
'/stencil.config.js': `
function myPlugin() {
return {
transform: function(sourceText) {
return sourceText.replace('constructor() { }', 'constructor(){console.log("transformed!")}');
},
name: 'myPlugin'
};
}
exports.config = {
plugins: [myPlugin()]
};
`,
'/src/cmp-a.tsx': `
@Component({ tag: 'cmp-a' }) export class CmpA {
constructor() { }
}
`
}, { clearFileCache: true });
await c.fs.commit();

c.loadConfigFile('/stencil.config.js');

const r = await c.build();
expect(r.diagnostics).toEqual([]);

const cmpA = await c.fs.readFile('/www/build/app/cmp-a.js');
expect(cmpA).toContain('transformed!');
});

it('resolveId, async', async () => {
c.config.bundles = [ { components: ['cmp-a'] } ];

await c.fs.writeFiles({
'/stencil.config.js': `
function myPlugin() {
return {
resolveId: function(importee, importer) {
if (importee === '#crazy-path!') {
return Promise.resolve('/dist/my-dep-fn.js');
}
},
name: 'myPlugin'
};
}
exports.config = {
plugins: [myPlugin()]
};
`,
'/src/cmp-a.tsx': `
import { depFn } '#crazy-path!'
@Component({ tag: 'cmp-a' }) export class CmpA {
constructor() {
depFn();
}
}
`,
'/dist/my-dep-fn.js': `
export function depFn(){
console.log('imported depFun()');
}
`
}, { clearFileCache: true });
await c.fs.commit();

c.loadConfigFile('/stencil.config.js');

const r = await c.build();
expect(r.diagnostics).toEqual([]);

const cmpA = await c.fs.readFile('/www/build/app/cmp-a.js');
expect(cmpA).toContain('imported depFun()');
});

it('resolveId, sync', async () => {
c.config.bundles = [ { components: ['cmp-a'] } ];

await c.fs.writeFiles({
'/stencil.config.js': `
function myPlugin() {
return {
resolveId: function(importee, importer) {
if (importee === '#crazy-path!') {
return '/dist/my-dep-fn.js';
}
},
name: 'myPlugin'
};
}
exports.config = {
plugins: [myPlugin()]
};
`,
'/src/cmp-a.tsx': `
import { depFn } '#crazy-path!'
@Component({ tag: 'cmp-a' }) export class CmpA {
constructor() {
depFn();
}
}
`,
'/dist/my-dep-fn.js': `
export function depFn(){
console.log('imported depFun()');
}
`
}, { clearFileCache: true });
await c.fs.commit();

c.loadConfigFile('/stencil.config.js');

const r = await c.build();
expect(r.diagnostics).toEqual([]);

const cmpA = await c.fs.readFile('/www/build/app/cmp-a.js');
expect(cmpA).toContain('imported depFun()');
});


});
58 changes: 31 additions & 27 deletions src/compiler/style/style-minify-plugin.ts
@@ -1,42 +1,46 @@
import * as d from '../../declarations/index';


export class StyleMinifyPlugin implements d.Plugin {
export default function styleMinifyPlugin(): d.Plugin {
const name = 'styleMinifyPlugin';

async transform(sourceText: string, id: string, context: d.PluginCtx): Promise<d.PluginTransformResults> {
if (!context.config.minifyCss || !this.usePlugin(id)) {
return null;
}
return {

const results: d.PluginTransformResults = {};
transform: async function(sourceText: string, id: string, context: d.PluginCtx): Promise<d.PluginTransformResults> {
if (!context || !context.config.minifyCss || !usePlugin(id)) {
return null;
}

const results: d.PluginTransformResults = {};

const cacheKey = context.cache.createKey(this.name, sourceText);
const cachedContent = await context.cache.get(cacheKey);
const cacheKey = context.cache.createKey(name, sourceText);
const cachedContent = await context.cache.get(cacheKey);

if (cachedContent != null) {
results.code = cachedContent;
if (cachedContent != null) {
results.code = cachedContent;

} else {
const minifyResults = context.sys.minifyCss(sourceText);
minifyResults.diagnostics.forEach(d => {
context.diagnostics.push(d);
});
} else {
const minifyResults = context.sys.minifyCss(sourceText);
minifyResults.diagnostics.forEach(d => {
context.diagnostics.push(d);
});

if (typeof minifyResults.output === 'string') {
results.code = minifyResults.output;
await context.cache.put(cacheKey, results.code);
if (typeof minifyResults.output === 'string') {
results.code = minifyResults.output;
await context.cache.put(cacheKey, results.code);
}
}
}

return results;
}
return results;
},

name: name

usePlugin(id: string) {
return /(.css)$/i.test(id);
}
};

}

get name() {
return 'StyleMinifyPlugin';
}

function usePlugin(id: string) {
return /(.css)$/i.test(id);
}

0 comments on commit b8abbce

Please sign in to comment.