Skip to content

Commit

Permalink
🔀 Merge pull request #19 from gluons/ssr
Browse files Browse the repository at this point in the history
✨ Add SSR support
  • Loading branch information
gluons authored Sep 22, 2018
2 parents 00d5349 + 8481886 commit 25a63ea
Show file tree
Hide file tree
Showing 15 changed files with 302 additions and 55 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@
"url": "git+https://github.com/gluons/vue-pack.git"
},
"devDependencies": {
"@types/cheerio": "^0.22.9",
"@types/jest": "^23.3.2",
"@types/node": "8",
"@types/webpack": "^4.4.11",
"@vue/server-test-utils": "^1.0.0-beta.25",
"@vue/test-utils": "^1.0.0-beta.25",
"babel-core": "^6.26.3",
"babel-jest": "^23.6.0",
"chalk": "^2.4.1",
"cheerio": "^1.0.0-rc.2",
"cross-env": "^5.2.0",
"jest": "^23.6.0",
"lerna": "^3.4.0",
Expand All @@ -33,6 +36,7 @@
"typescript": "^3.0.3",
"vue": "^2.5.17",
"vue-class-component": "^6.2.0",
"vue-server-renderer": "^2.5.17",
"vue-template-compiler": "^2.5.17"
}
}
5 changes: 5 additions & 0 deletions packages/@gluons/plugin-splitchunks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ const options = {

return splitChunks;
},
tapSSR(splitChunks) {
// Do anything with `splitChunks`

return splitChunks;
}
tapWeb(splitChunks) {
// Do anything with `splitChunks`

Expand Down
24 changes: 22 additions & 2 deletions packages/@gluons/plugin-splitchunks/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,37 @@ export { TapFunction };
export interface SplitChunksPluginOptions {
/**
* A function to tap `splitChunks` in all configs
*
* @type {TapFunction}
* @memberof SplitChunksPluginOptions
*/
tapAll?: TapFunction;
/**
* A function to tap `splitChunks` in CommonJS config
*
* @type {TapFunction}
* @memberof SplitChunksPluginOptions
*/
tapCJS?: TapFunction;
/**
* A function to tap `splitChunks` in ES module config
*
* @type {TapFunction}
* @memberof SplitChunksPluginOptions
*/
tapESM?: TapFunction;
/**
* A function to tap `splitChunks` in SSR config
*
* @type {TapFunction}
* @memberof SplitChunksPluginOptions
*/
tapSSR?: TapFunction;
/**
* A function to tap `splitChunks` in web config.
*
* @type {TapFunction}
* @memberof SplitChunksPluginOptions
*/
tapWeb?: TapFunction;
}
Expand All @@ -49,10 +68,11 @@ export default function SplitChunksPlugin(options?: SplitChunksPluginOptions): P
tapSplitChunks(config, options.tapAll);
});
}
// tslint:disable:no-unused-expression

(typeof options.tapCJS === 'function') && tapSplitChunks(webpackConfigs.commonJSConfig, options.tapCJS);
(typeof options.tapESM === 'function') && tapSplitChunks(webpackConfigs.esModuleConfig, options.tapESM);
// tslint:enable:no-unused-expression
(typeof options.tapSSR === 'function') && tapSplitChunks(webpackConfigs.ssrConfig, options.tapSSR);

if (typeof options.tapWeb === 'function') {
tapSplitChunks(webpackConfigs.webUnminConfig, options.tapWeb);
tapSplitChunks(webpackConfigs.webMinConfig, options.tapWeb);
Expand Down
55 changes: 51 additions & 4 deletions packages/@gluons/plugin-splitchunks/test/splitChunks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,22 @@ const tapESM = splitChunks => Object.assign({}, splitChunks, {
}
});

const tapWeb = splitChunks => Object.assign({}, splitChunks, {
const tapSSR = splitChunks => Object.assign({}, splitChunks, {
cacheGroups: {
vendors: {
test: /vendors4/
}
}
});

const tapWeb = splitChunks => Object.assign({}, splitChunks, {
cacheGroups: {
vendors: {
test: /vendors5/
}
}
});

describe('SplitChunksPlugin', () => {
it('should change `splitChunks` in all configs', async () => {
const vuePackConfig: VuePackConfig = {
Expand Down Expand Up @@ -141,14 +149,14 @@ describe('SplitChunksPlugin', () => {
}
});

it('should change `splitChunks` in only web config', async () => {
it('should change `splitChunks` in only SSR config', async () => {
const vuePackConfig: VuePackConfig = {
entry: 'index.ts',
libraryName: 'Test',
externals: {}, // Prevent destructuring error
plugins: [
SplitChunksPlugin({
tapWeb
tapSSR
})
]
};
Expand All @@ -160,7 +168,7 @@ describe('SplitChunksPlugin', () => {

expect(config.optimization).toHaveProperty('splitChunks');

if ((i === 2) || (i === 3)) {
if (i === 2) {
expect(config.optimization.splitChunks).toMatchObject({
cacheGroups: {
vendors: {
Expand All @@ -179,4 +187,43 @@ describe('SplitChunksPlugin', () => {
}
}
});

it('should change `splitChunks` in only web config', async () => {
const vuePackConfig: VuePackConfig = {
entry: 'index.ts',
libraryName: 'Test',
externals: {}, // Prevent destructuring error
plugins: [
SplitChunksPlugin({
tapWeb
})
]
};

const configs: Configuration[] = await createConfigs(vuePackConfig);

for (let i = 0; i < configs.length; i++) { // tslint:disable-line: prefer-for-of
const config = configs[i];

expect(config.optimization).toHaveProperty('splitChunks');

if ((i === 3) || (i === 4)) {
expect(config.optimization.splitChunks).toMatchObject({
cacheGroups: {
vendors: {
test: /vendors5/
}
}
});
} else {
expect(config.optimization.splitChunks).not.toMatchObject({
cacheGroups: {
vendors: {
test: /vendors5/
}
}
});
}
}
});
});
11 changes: 4 additions & 7 deletions packages/@gluons/types/src/Configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,8 @@ export function toBaseOptions(config: Configuration): BaseOptions {
* @returns {WebOptions}
*/
export function toWebOptions(config: Configuration, minimize: boolean): WebOptions {
const webOptions: WebOptions = Object.assign(
{},
pick(config, [
const webOptions: WebOptions = {
...pick(config, [
'entry',
'libraryName',
'fileName',
Expand All @@ -154,10 +153,8 @@ export function toWebOptions(config: Configuration, minimize: boolean): WebOptio
'externals',
'sourceMap'
]),
{
minimize
}
);
minimize
};

return webOptions;
}
19 changes: 19 additions & 0 deletions packages/@gluons/types/src/WebpackChainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,37 @@
export interface WebpackChainConfigGroup {
/**
* Common JS `webpack-chain`'s config instance
*
* @type {any}
* @memberof WebpackChainConfigGroup
*/
readonly commonJSConfig: any;
/**
* ES module `webpack-chain`'s config instance
*
* @type {any}
* @memberof WebpackChainConfigGroup
*/
readonly esModuleConfig: any;
/**
* SSR (Server-Side Rendering) `webpack-chain`'s config instance
*
* @type {any}
* @memberof WebpackChainConfigGroup
*/
readonly ssrConfig: any;
/**
* Unminified web `webpack-chain`'s config instance
*
* @type {any}
* @memberof WebpackChainConfigGroup
*/
readonly webUnminConfig: any;
/**
* Minified web `webpack-chain`'s config instance
*
* @type {any}
* @memberof WebpackChainConfigGroup
*/
readonly webMinConfig: any;
}
Expand Down
34 changes: 16 additions & 18 deletions packages/@gluons/vue-pack/src/createConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
} from '@gluons/vue-pack-types';
import { Configuration as WebpackConfiguration } from 'webpack';

import createModuleConfig, { Options as CreateModuleConfigOptions } from './lib/createModuleConfig';
import createModuleConfig from './lib/createModuleConfig';
import createWebConfig from './lib/createWebConfig';
import executeChainWebpack from './lib/executeChainWebpack';
import executePlugins from './lib/executePlugins';
Expand All @@ -16,6 +16,7 @@ const { toBaseOptions, toWebOptions } = ConfigurationMethods;
const barOptions = [
{ name: 'CommonJS', color: 'green' },
{ name: 'ES Module', color: 'magenta' },
{ name: 'Server-Side Rendering', color: 'blue' },
{ name: 'Web Unminified', color: 'cyan' },
{ name: 'Web Minified', color: 'yellow' }
];
Expand All @@ -29,23 +30,18 @@ const barOptions = [
*/
export default async function createConfigs(config: Configuration): Promise<WebpackConfiguration[]> {
const baseOptions = toBaseOptions(config);
const commonJSOptions: CreateModuleConfigOptions = Object.assign(
{},
baseOptions,
{
moduleType: 'common'
} as CreateModuleConfigOptions
);
const esModuleOptions: CreateModuleConfigOptions = Object.assign(
{},
baseOptions,
{
moduleType: 'es'
} as CreateModuleConfigOptions
);

const commonJSConfig = await createModuleConfig(commonJSOptions);
const esModuleConfig = await createModuleConfig(esModuleOptions);
const commonJSConfig = await createModuleConfig({
...baseOptions,
moduleType: 'common'
});
const esModuleConfig = await createModuleConfig({
...baseOptions,
moduleType: 'es'
});
const ssrConfig = await createModuleConfig({
...baseOptions,
moduleType: 'ssr'
});
const webUnminConfig = await createWebConfig(toWebOptions(config, false));
const webMinConfig = await createWebConfig(toWebOptions(config, true));

Expand All @@ -55,6 +51,7 @@ export default async function createConfigs(config: Configuration): Promise<Webp
const allConfigs = [
commonJSConfig,
esModuleConfig,
ssrConfig,
webUnminConfig,
webMinConfig
];
Expand All @@ -65,6 +62,7 @@ export default async function createConfigs(config: Configuration): Promise<Webp
const webpackConfigGroup: WebpackChainConfigGroup = {
commonJSConfig,
esModuleConfig,
ssrConfig,
webUnminConfig,
webMinConfig
};
Expand Down
4 changes: 1 addition & 3 deletions packages/@gluons/vue-pack/src/lib/createBaseConfig.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { BaseOptions } from '@gluons/vue-pack-types';
import Config from 'webpack-chain';

import infuseAliases from './infuseAliases';
import infuseWebpackModule from './infuser/infuseWebpackModule';
import infuseAliases from './infuser/infuseAliases';

/**
* Create base config via `webpack-chain`'s config instance.
Expand Down Expand Up @@ -40,7 +39,6 @@ export default async function createBaseConfig(options: BaseOptions): Promise<an
;

infuseAliases(config, alias);
await infuseWebpackModule(config, outDir, sourceMap);

return config;
}
16 changes: 14 additions & 2 deletions packages/@gluons/vue-pack/src/lib/createModuleConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { BaseOptions } from '@gluons/vue-pack-types';
import createBaseConfig from './createBaseConfig';
import infuseCJSOutput from './infuser/infuseCJSOutput';
import infuseESMOutput from './infuser/infuseESMOutput';
import infuseSSROutput from './infuser/infuseSSROutput';
import infuseWebpackModule from './infuser/infuseWebpackModule';
import infuseWebpackOptimization from './infuser/infuseWebpackOptimization';
import infuseWebpackPlugins from './infuser/infuseWebpackPlugins';

export type Options = BaseOptions & { moduleType: 'common' | 'es' };
export type Options = BaseOptions & { moduleType: 'common' | 'es' | 'ssr' };

/**
* Create module config via `webpack-chain`'s config instance.
Expand All @@ -18,6 +20,7 @@ export type Options = BaseOptions & { moduleType: 'common' | 'es' };
export default async function createModuleConfig(options: Options): Promise<any> {
const {
fileName,
outDir,
define,
sourceMap,
externals: { module: moduleExternals },
Expand All @@ -27,11 +30,20 @@ export default async function createModuleConfig(options: Options): Promise<any>

if (moduleType === 'common') {
infuseCJSOutput(config);
} else {
} else if (moduleType === 'es') {
infuseESMOutput(config);
} else {
infuseSSROutput(config);
config.target('node');
}

infuseWebpackOptimization(config, false);
await infuseWebpackModule({
config,
outDir,
sourceMap,
ssr: moduleType === 'ssr'
});
infuseWebpackPlugins({
config,
fileName,
Expand Down
Loading

0 comments on commit 25a63ea

Please sign in to comment.