remove unnecessary template declarations - fixes #440

pull/447/head
Rich Harris 8 years ago
parent 4b5754b9a7
commit d2db41f811

@ -266,10 +266,11 @@ export default class Generator {
const imports = this.imports; const imports = this.imports;
const computations = []; const computations = [];
let defaultExport = null;
let namespace = null;
const templateProperties = {}; const templateProperties = {};
let namespace = null;
let hasJs = !!js;
if ( js ) { if ( js ) {
this.addSourcemapLocations( js.content ); this.addSourcemapLocations( js.content );
const body = js.content.body.slice(); // slice, because we're going to be mutating the original const body = js.content.body.slice(); // slice, because we're going to be mutating the original
@ -287,38 +288,14 @@ export default class Generator {
} }
} }
defaultExport = body.find( node => node.type === 'ExportDefaultDeclaration' ); const defaultExport = body.find( node => node.type === 'ExportDefaultDeclaration' );
if ( defaultExport ) { if ( defaultExport ) {
const finalNode = body[ body.length - 1 ];
if ( defaultExport === finalNode ) {
// export is last property, we can just return it
this.code.overwrite( defaultExport.start, defaultExport.declaration.start, `return ` );
} else {
const { declarations } = annotateWithScopes( js );
let template = 'template';
for ( let i = 1; declarations.has( template ); template = `template_${i++}` );
this.code.overwrite( defaultExport.start, defaultExport.declaration.start, `var ${template} = ` );
let i = defaultExport.start;
while ( /\s/.test( source[ i - 1 ] ) ) i--;
const indentation = source.slice( i, defaultExport.start );
this.code.appendLeft( finalNode.end, `\n\n${indentation}return ${template};` );
}
defaultExport.declaration.properties.forEach( prop => { defaultExport.declaration.properties.forEach( prop => {
templateProperties[ prop.key.name ] = prop; templateProperties[ prop.key.name ] = prop;
}); });
this.code.prependRight( js.content.start, `var ${this.alias( 'template' )} = (function () {` );
} else {
this.code.prependRight( js.content.start, '(function () {' );
} }
this.code.appendLeft( js.content.end, '}());' );
[ 'helpers', 'events', 'components' ].forEach( key => { [ 'helpers', 'events', 'components' ].forEach( key => {
if ( templateProperties[ key ] ) { if ( templateProperties[ key ] ) {
templateProperties[ key ].value.properties.forEach( prop => { templateProperties[ key ].value.properties.forEach( prop => {
@ -383,10 +360,51 @@ export default class Generator {
removeObjectKey( this.code, defaultExport.declaration, 'components' ); removeObjectKey( this.code, defaultExport.declaration, 'components' );
} }
} }
// now that we've analysed the default export, we can determine whether or not we need to keep it
let hasDefaultExport = !!defaultExport;
if ( defaultExport && defaultExport.declaration.properties.length === 0 ) {
hasDefaultExport = false;
removeNode( this.code, js.content, defaultExport );
}
// if we do need to keep it, then we need to generate a return statement
if ( hasDefaultExport ) {
const finalNode = body[ body.length - 1 ];
if ( defaultExport === finalNode ) {
// export is last property, we can just return it
this.code.overwrite( defaultExport.start, defaultExport.declaration.start, `return ` );
} else {
const { declarations } = annotateWithScopes( js );
let template = 'template';
for ( let i = 1; declarations.has( template ); template = `template_${i++}` );
this.code.overwrite( defaultExport.start, defaultExport.declaration.start, `var ${template} = ` );
let i = defaultExport.start;
while ( /\s/.test( source[ i - 1 ] ) ) i--;
const indentation = source.slice( i, defaultExport.start );
this.code.appendLeft( finalNode.end, `\n\n${indentation}return ${template};` );
}
}
// user code gets wrapped in an IIFE
if ( js.content.body.length ) {
const prefix = hasDefaultExport ? `var ${this.alias( 'template' )} = (function () {` : `(function () {`;
this.code.prependRight( js.content.start, prefix ).appendLeft( js.content.end, '}());' );
}
// if there's no need to include user code, remove it altogether
else {
this.code.remove( js.content.start, js.content.end );
hasJs = false;
}
} }
return { return {
computations, computations,
hasJs,
namespace, namespace,
templateProperties templateProperties
}; };

@ -151,7 +151,7 @@ export default function dom ( parsed, source, options ) {
const generator = new DomGenerator( parsed, source, name, visitors, options ); const generator = new DomGenerator( parsed, source, name, visitors, options );
const { computations, templateProperties, namespace } = generator.parseJs(); const { computations, hasJs, templateProperties, namespace } = generator.parseJs();
// Remove these after version 2 // Remove these after version 2
if ( templateProperties.onrender ) { if ( templateProperties.onrender ) {
@ -239,7 +239,7 @@ export default function dom ( parsed, source, options ) {
${generator.helper( 'dispatchObservers' )}( this, this._observers.post, newState, oldState ); ${generator.helper( 'dispatchObservers' )}( this, this._observers.post, newState, oldState );
` ); ` );
if ( parsed.js ) { if ( hasJs ) {
builders.main.addBlock( `[✂${parsed.js.content.start}-${parsed.js.content.end}✂]` ); builders.main.addBlock( `[✂${parsed.js.content.start}-${parsed.js.content.end}✂]` );
} }

@ -40,7 +40,7 @@ export default function ssr ( parsed, source, options ) {
const generator = new SsrGenerator( parsed, source, name, visitors, options ); const generator = new SsrGenerator( parsed, source, name, visitors, options );
const { computations, templateProperties } = generator.parseJs(); const { computations, hasJs, templateProperties } = generator.parseJs();
const builders = { const builders = {
main: new CodeBuilder(), main: new CodeBuilder(),
@ -131,7 +131,7 @@ export default function ssr ( parsed, source, options ) {
}; };
` ); ` );
if ( parsed.js ) { if ( hasJs ) {
builders.main.addBlock( `[✂${parsed.js.content.start}-${parsed.js.content.end}✂]` ); builders.main.addBlock( `[✂${parsed.js.content.start}-${parsed.js.content.end}✂]` );
} }

Loading…
Cancel
Save