Skip to content
This repository was archived by the owner on Jan 11, 2023. It is now read-only.

minify HTML templates #193

Merged
merged 4 commits into from
Mar 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "sapper",
"version": "0.9.3",
"description": "Military-grade apps, engineered by Svelte",
"main": "middleware.js",
"main": "dist/middleware.ts.js",
"bin": {
"sapper": "./sapper"
},
Expand All @@ -23,6 +23,7 @@
"clorox": "^1.0.3",
"devalue": "^1.0.1",
"glob": "^7.1.2",
"html-minifier": "^3.5.10",
"mkdirp": "^0.5.1",
"node-fetch": "^1.7.3",
"polka": "^0.3.4",
Expand Down
10 changes: 8 additions & 2 deletions src/cli/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import * as path from 'path';
import * as clorox from 'clorox';
import mkdirp from 'mkdirp';
import rimraf from 'rimraf';
import { minify_html } from './utils/minify_html';
import { create_compilers, create_main_manifests, create_routes, create_serviceworker_manifest } from '../core'
import { dest } from '../config';
import { locations } from '../config';

export async function build() {
const output = dest();
const output = locations.dest();

mkdirp.sync(output);
rimraf.sync(path.join(output, '**/*'));
Expand Down Expand Up @@ -40,6 +41,11 @@ export async function build() {
console.log(clorox.inverse(`\nbuilt service worker`).toString());
console.log(serviceworker_stats.toString({ colors: true }));
}

// minify app/template.html
// TODO compile this to a function? could be quicker than str.replace(...).replace(...).replace(...)
const template = fs.readFileSync(`${locations.app()}/template.html`, 'utf-8');
fs.writeFileSync(`${output}/template.html`, minify_html(template));
}

function compile(compiler: any) {
Expand Down
8 changes: 4 additions & 4 deletions src/cli/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import rimraf from 'rimraf';
import format_messages from 'webpack-format-messages';
import prettyMs from 'pretty-ms';
import * as ports from 'port-authority';
import { dest } from '../config';
import { locations } from '../config';
import { create_compilers, create_main_manifests, create_routes, create_serviceworker_manifest } from '../core';

type Deferred = {
Expand Down Expand Up @@ -84,7 +84,7 @@ export async function dev(opts: { port: number }) {
port = await ports.find(3000);
}

const dir = dest();
const dir = locations.dest();
rimraf.sync(dir);
mkdirp.sync(dir);

Expand All @@ -95,12 +95,12 @@ export async function dev(opts: { port: number }) {

const hot_update_server = create_hot_update_server(dev_port);

watch_files('routes/**/*', ['add', 'unlink'], () => {
watch_files(`${locations.routes()}/**/*`, ['add', 'unlink'], () => {
const routes = create_routes();
create_main_manifests({ routes, dev_port });
});

watch_files('app/template.html', ['change'], () => {
watch_files(`${locations.app()}/template.html`, ['change'], () => {
hot_update_server.send({
action: 'reload'
});
Expand Down
4 changes: 2 additions & 2 deletions src/cli/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import cheerio from 'cheerio';
import URL from 'url-parse';
import fetch from 'node-fetch';
import * as ports from 'port-authority';
import { dest } from '../config';
import { locations } from '../config';

export async function exporter(export_dir: string) {
const build_dir = dest();
const build_dir = locations.dest();

// Prep output directory
sander.rimrafSync(export_dir);
Expand Down
21 changes: 21 additions & 0 deletions src/cli/utils/minify_html.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { minify } from 'html-minifier';

export function minify_html(html: string) {
return minify(html, {
collapseBooleanAttributes: true,
collapseWhitespace: true,
conservativeCollapse: true,
decodeEntities: true,
html5: true,
minifyCSS: true,
minifyJS: true,
removeAttributeQuotes: true,
removeComments: true,
removeOptionalTags: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
sortAttributes: true,
sortClassName: true
});
}
9 changes: 7 additions & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import * as path from 'path';

export const dev = () => process.env.NODE_ENV !== 'production';
export const src = () => path.resolve(process.env.SAPPER_ROUTES || 'routes');
export const dest = () => path.resolve(process.env.SAPPER_DEST || '.sapper');

export const locations = {
base: () => path.resolve(process.env.SAPPER_BASE || ''),
app: () => path.resolve(process.env.SAPPER_BASE || '', process.env.SAPPER_APP || 'app'),
routes: () => path.resolve(process.env.SAPPER_BASE || '', process.env.SAPPER_ROUTES || 'routes'),
dest: () => path.resolve(process.env.SAPPER_BASE || '', process.env.SAPPER_DEST || '.sapper')
};
22 changes: 12 additions & 10 deletions src/core/create_manifests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ import * as path from 'path';
import * as glob from 'glob';
import create_routes from './create_routes';
import { posixify, write_if_changed } from './utils';
import { dev } from '../config';
import { dev, locations } from '../config';
import { Route } from '../interfaces';

export function create_main_manifests({ routes, dev_port }: {
routes: Route[];
dev_port?: number;
}) {
const client_manifest = generate_client(routes, dev_port);
const server_manifest = generate_server(routes);
const path_to_routes = path.relative(`${locations.app()}/manifest`, locations.routes());

write_if_changed(`app/manifest/client.js`, client_manifest);
write_if_changed(`app/manifest/server.js`, server_manifest);
const client_manifest = generate_client(routes, path_to_routes, dev_port);
const server_manifest = generate_server(routes, path_to_routes);

write_if_changed(`${locations.app()}/manifest/client.js`, client_manifest);
write_if_changed(`${locations.app()}/manifest/server.js`, server_manifest);
}

export function create_serviceworker_manifest({ routes, client_files }: {
Expand All @@ -34,10 +36,10 @@ export function create_serviceworker_manifest({ routes, client_files }: {
export const routes = [\n\t${routes.filter((r: Route) => r.type === 'page' && !/^_[45]xx$/.test(r.id)).map((r: Route) => `{ pattern: ${r.pattern} }`).join(',\n\t')}\n];
`.replace(/^\t\t/gm, '').trim();

write_if_changed('app/manifest/service-worker.js', code);
write_if_changed(`${locations.app()}/manifest/service-worker.js`, code);
}

function generate_client(routes: Route[], dev_port?: number) {
function generate_client(routes: Route[], path_to_routes: string, dev_port?: number) {
let code = `
// This file is generated by Sapper — do not edit it!
export const routes = [
Expand All @@ -47,7 +49,7 @@ function generate_client(routes: Route[], dev_port?: number) {
return `{ pattern: ${route.pattern}, ignore: true }`;
}

const file = posixify(`../../routes/${route.file}`);
const file = posixify(`${path_to_routes}/${route.file}`);

if (route.id === '_4xx' || route.id === '_5xx') {
return `{ error: '${route.id.slice(1)}', load: () => import(/* webpackChunkName: "${route.id}" */ '${file}') }`;
Expand Down Expand Up @@ -79,12 +81,12 @@ function generate_client(routes: Route[], dev_port?: number) {
return code;
}

function generate_server(routes: Route[]) {
function generate_server(routes: Route[], path_to_routes: string) {
let code = `
// This file is generated by Sapper — do not edit it!
${routes
.map(route => {
const file = posixify(`../../routes/${route.file}`);
const file = posixify(`${path_to_routes}/${route.file}`);
return route.type === 'page'
? `import ${route.id} from '${file}';`
: `import * as ${route.id} from '${file}';`;
Expand Down
4 changes: 2 additions & 2 deletions src/core/create_routes.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as path from 'path';
import glob from 'glob';
import { src } from '../config';
import { locations } from '../config';
import { Route } from '../interfaces';

export default function create_routes({ files } = { files: glob.sync('**/*.*', { cwd: src(), nodir: true }) }) {
export default function create_routes({ files } = { files: glob.sync('**/*.*', { cwd: locations.routes(), nodir: true }) }) {
const routes: Route[] = files
.map((file: string) => {
if (/(^|\/|\\)_/.test(file)) return;
Expand Down
10 changes: 5 additions & 5 deletions src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import rimraf from 'rimraf';
import devalue from 'devalue';
import { lookup } from './middleware/mime';
import { create_routes, create_compilers } from './core';
import { dest, dev } from './config';
import { locations, dev } from './config';
import { Route, Template } from './interfaces';
import sourceMapSupport from 'source-map-support';

Expand Down Expand Up @@ -40,7 +40,7 @@ interface Req extends ClientRequest {
export default function middleware({ routes }: {
routes: RouteObject[]
}) {
const output = dest();
const output = locations.dest();

const client_info = JSON.parse(fs.readFileSync(path.join(output, 'client_info.json'), 'utf-8'));

Expand Down Expand Up @@ -80,7 +80,7 @@ function serve({ prefix, pathname, cache_control }: {
? (req: Req) => req.pathname === pathname
: (req: Req) => req.pathname.startsWith(prefix);

const output = dest();
const output = locations.dest();

const cache: Map<string, Buffer> = new Map();

Expand Down Expand Up @@ -112,8 +112,8 @@ const resolved = Promise.resolve();

function get_route_handler(chunks: Record<string, string>, routes: RouteObject[]) {
const template = dev()
? () => fs.readFileSync('app/template.html', 'utf-8')
: (str => () => str)(fs.readFileSync('app/template.html', 'utf-8'));
? () => fs.readFileSync(`${locations.app()}/template.html`, 'utf-8')
: (str => () => str)(fs.readFileSync(`${locations.dest()}/template.html`, 'utf-8'));

function handle_route(route: RouteObject, req: Req, res: ServerResponse) {
req.params = route.params(route.pattern.exec(req.pathname));
Expand Down
14 changes: 7 additions & 7 deletions src/webpack.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { dest, dev } from './config';
import { locations, dev } from './config';

export default {
dev: dev(),

client: {
entry: () => {
return {
main: './app/client'
main: `${locations.app()}/client`
};
},

output: () => {
return {
path: `${dest()}/client`,
path: `${locations.dest()}/client`,
filename: '[hash]/[name].js',
chunkFilename: '[hash]/[name].[id].js',
publicPath: '/client/'
Expand All @@ -23,13 +23,13 @@ export default {
server: {
entry: () => {
return {
server: './app/server'
server: `${locations.app()}/server`
};
},

output: () => {
return {
path: dest(),
path: locations.dest(),
filename: '[name].js',
chunkFilename: '[hash]/[name].[id].js',
libraryTarget: 'commonjs2'
Expand All @@ -40,13 +40,13 @@ export default {
serviceworker: {
entry: () => {
return {
'service-worker': './app/service-worker'
'service-worker': `${locations.app()}/service-worker`
};
},

output: () => {
return {
path: dest(),
path: locations.dest(),
filename: '[name].js',
chunkFilename: '[name].[id].[hash].js'
}
Expand Down