Skip to content

Commit

Permalink
feat:support injectRes config
Browse files Browse the repository at this point in the history
  • Loading branch information
hubcarl committed Jul 5, 2017
1 parent c3aaca3 commit 8326cb9
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 18 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ exports.vuessr = {
// buildConfig: path.join(app.baseDir, 'config/buildConfig.json'),
// injectCss: true,
// injectJs: true,
// injectRes: []
// fallbackToClient: true, // fallback to client rendering after server rendering failed
// afterRender: (html, context) => {
// return html;
Expand Down
5 changes: 5 additions & 0 deletions config/config.default.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ module.exports = app => {
* @property {String} [manifest=${baseDir}/config/buildConfig.json] - compile config, include `publicPath` and `commonsChunk`
* @property {Boolean} [injectCss] whether inject href css
* @property {Boolean} [injectJs] whether inject src script
* @property {Array} [injectRes] inline/inject css or js to file head or body. include location and src config
* inline {Boolean} true or false, default false
* location {String} headBefore, headAfter, bodyBefore, bodyAfter insert location, default headBefore
* url {String} inline file absolution path
* @property {Function} afterRender hook html after render
* `publicPath`: static resource prefix path, so cdn domain address prefix or local prefix path(`/`)
* `commonsChunk`: common js or css filename, so `vendor`
Expand All @@ -22,6 +26,7 @@ module.exports = app => {
buildConfig: path.join(app.baseDir, 'config/buildConfig.json'),
injectCss: true,
injectJs: true,
injectRes: [],
fallbackToClient: true, // fallback to client rendering if server render failed
afterRender: (html, context) => { /* eslint no-unused-vars:off */
return html;
Expand Down
111 changes: 94 additions & 17 deletions lib/resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,60 @@ class Resource {
}

init() {
this.initConfig();
// local dev mode, webpack build finish update buildConfig and manifest
if (process.env.NODE_ENV !== 'production') {
this.app.messenger.on('webpack_manifest_save_success', () => {
delete require.cache[this.config.buildConfig];
delete require.cache[this.config.manifest];
this.initConfig();
});
}
}

initConfig() {
if (this.isValidJSONConfig(this.config.buildConfig)) {
this.buildConfig = require(this.config.buildConfig);
}
if (!this.resourceDeps && this.isValidJSONConfig(this.config.manifest)) {
if (this.isValidJSONConfig(this.config.manifest)) {
const manifest = require(this.config.manifest);
this.resourceDeps = this.getResourceDeps(manifest, this.buildConfig);
}
this.initInline();
}

initInline() {
if (Array.isArray(this.config.injectRes)) {
this.config.injectRes.forEach(item => {
if (item.inline && this.isExist(item.url)) {
const content = this.readFile(item.url);
if (/\.js$/.test(item.url)) {
item.content = `<script>${content}</script>`;
} else if (/\.css$/.test(item.url)) {
item.content = `<style>${content}</style>`;
}
} else {
if (/\.js$/.test(item.url)) {
item.content = this.createScriptSrcTag(item.url);
} else if (/\.css$/.test(item.url)) {
item.content = this.createCssLinkTag(item.url);
}
}
});
}
}

isExist(filepath) {
return fs.existsSync(filepath);
}

readFile(filepath) {
return fs.readFileSync(filepath, 'utf8');
}

isValidJSONConfig(filepath) {
if (!filepath) return false;
if (fs.existsSync(filepath)) {
if (this.isExist(filepath)) {
try {
return require(filepath);
} catch (err) {
Expand All @@ -33,35 +75,70 @@ class Resource {
return false;
}

createCssLinkTag(url) {
return `<link rel="stylesheet" href="${url}">`;
}

createScriptSrcTag(url) {
return `<script type="text/javascript" src="${url}"></script>`;
}

injectHead(resArr) {
this.config.injectRes.forEach(item => {
if (item.content) {
if (item.location === 'headBefore' || (item.location === undefined && /\.(css|js)$/.test(item.url))) {
resArr.unshift(item.content);
} else if (item.location === 'headAfter') {
resArr.push(item.content);
}
}
});
}

injectBody(resArr) {
this.config.injectRes.forEach(item => {
if (item.content) {
if (item.location === 'bodyBefore') {
resArr.unshift(item.content);
} else if (item.location === 'bodyAfter') {
resArr.push(item.content);
}
}
});
}


inject(name, html, context, config, options) {
this.init();
const fileKey = name;
const fileManifest = this.resourceDeps[fileKey];
if (fileManifest) {
const headInject = [];
const bodyInject = [];
const publicPath = this.buildConfig.publicPath;
if (config.injectCss && (options.injectCss === undefined || options.injectCss)) {
const cssInject = fileManifest.css.map(item => {
return `<link rel="stylesheet" href="${publicPath + item}">`;
});
html = html.replace(this.headRegExp, match => {
return cssInject.join('') + match;
fileManifest.css.forEach(item => {
headInject.push(this.createCssLinkTag(publicPath + item));
});
} else {
html = html.replace(this.headRegExp, match => {
return context.styles + match;
});
headInject.push(context.styles);
}
if (config.injectJs) {
const scriptInject = fileManifest.script.map(item => {
return `<script type="text/javascript" src="${publicPath + item}"></script>`;
fileManifest.script.forEach(item => {
bodyInject.push(this.createScriptSrcTag(publicPath + item));
});
if (!/window.__INITIAL_STATE__/.test(html)) {
scriptInject.unshift(`<script> window.__INITIAL_STATE__= ${serialize(context.state, { isJSON: true })};</script>`);
bodyInject.unshift(`<script> window.__INITIAL_STATE__= ${serialize(context.state, { isJSON: true })};</script>`);
}
html = html.replace(this.bodyRegExp, match => {
return scriptInject.join('') + match;
});
}
this.injectHead(headInject);
html = html.replace(this.headRegExp, match => {
return headInject.join('') + match;
});

this.injectBody(bodyInject);
html = html.replace(this.bodyRegExp, match => {
return bodyInject.join('') + match;
});
}
return config.afterRender(html, context);
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "egg-view-vue-ssr",
"version": "2.0.0",
"version": "2.0.1",
"description": "vue server side render solution for egg-view-vue",
"eggPlugin": {
"name": "vuessr",
Expand Down

0 comments on commit 8326cb9

Please sign in to comment.