polyserve
Version:
A simple dev server for bower components
149 lines • 6.54 kB
JavaScript
/**
* @license
* Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at
* http://polymer.github.io/LICENSE.txt
* The complete set of authors may be found at
* http://polymer.github.io/AUTHORS.txt
* The complete set of contributors may be found at
* http://polymer.github.io/CONTRIBUTORS.txt
* Code distributed by Google as part of the polymer project is also
* subject to an additional IP rights grant found at
* http://polymer.github.io/PATENTS.txt
*/
Object.defineProperty(exports, "__esModule", { value: true });
const browser_capabilities_1 = require("browser-capabilities");
const content_type_1 = require("content-type");
const fs = require("fs");
const LRU = require("lru-cache");
const path = require("path");
const polymer_build_1 = require("polymer-build");
const get_compile_target_1 = require("./get-compile-target");
const transform_middleware_1 = require("./transform-middleware");
const javaScriptMimeTypes = [
'application/javascript',
'application/ecmascript',
'text/javascript',
'text/ecmascript',
];
const htmlMimeType = 'text/html';
const compileMimeTypes = [htmlMimeType, ...javaScriptMimeTypes];
// Match the polyfills from https://github.com/webcomponents/webcomponentsjs,
// but not their tests.
exports.isPolyfill = /(^|\/)webcomponentsjs\/[^\/]+$/;
function getContentType(response) {
const contentTypeHeader = response.get('Content-Type');
return contentTypeHeader && content_type_1.parse(contentTypeHeader).type;
}
// NOTE: To change the max length of the cache at runtime, just use bracket
// notation, i.e. `babelCompileCache['max'] = 64 * 1024` for 64KB limit.
exports.babelCompileCache = LRU({
length: (n, key) => n.length + key.length
});
// TODO(justinfagnani): see if we can just use the request path as the key
// See https://github.com/Polymer/polyserve/issues/248
exports.getCompileCacheKey = (requestPath, body, options) => JSON.stringify(options) + requestPath + body;
function babelCompile(compile, moduleResolution, rootDir, packageName, componentUrl, componentDir) {
return transform_middleware_1.transformResponse({
shouldTransform(request, response) {
// We must never compile the Custom Elements ES5 Adapter or other
// polyfills/shims.
if (exports.isPolyfill.test(request.url)) {
return false;
}
if ('nocompile' in request.query) {
return false;
}
if (!compileMimeTypes.includes(getContentType(response))) {
return false;
}
if (compile === 'always' || moduleResolution === 'node') {
return true;
}
if (compile === 'never') {
return false;
}
const capabilities = browser_capabilities_1.browserCapabilities(request.get('user-agent'));
return !capabilities.has('es2015') || !capabilities.has('modules');
},
transform(request, response, body) {
const capabilities = browser_capabilities_1.browserCapabilities(request.get('user-agent'));
const compileTarget = get_compile_target_1.getCompileTarget(capabilities, compile);
const options = {
compileTarget,
transformModules: compile === 'always' || !capabilities.has('modules'),
};
const cacheKey = exports.getCompileCacheKey(request.baseUrl + request.path, body, options);
const cached = exports.babelCompileCache.get(cacheKey);
if (cached !== undefined) {
return cached;
}
// Make sure that componentDir is absolute, like jsTransform expects
componentDir = path.resolve(rootDir, componentDir);
let transformed;
const contentType = getContentType(response);
let requestPath = request.path;
// TODO(justinfagnani): Use path-is-inside, but test on Windows
const isRootPathRequest = request.path === `/${packageName}` ||
request.path.startsWith(`/${packageName}/`);
const isComponentRequest = request.baseUrl === `/${componentUrl}`;
let filePath;
if (isRootPathRequest) {
requestPath = requestPath.substring(`/${packageName}`.length);
}
if (isComponentRequest && !isRootPathRequest) {
filePath = path.join(componentDir, requestPath);
}
else {
filePath = path.join(rootDir, requestPath);
}
// The file path needs to include the filename for correct relative
// path calculation
try {
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
filePath = path.join(filePath, 'index.html');
}
}
catch (e) {
// file not found, will 404 later
}
if (contentType === htmlMimeType) {
transformed = polymer_build_1.htmlTransform(body, {
js: {
compile: options.compileTarget,
moduleResolution,
filePath,
packageName,
isComponentRequest,
componentDir,
rootDir,
transformModulesToAmd: options.transformModules,
softSyntaxError: true,
},
injectAmdLoader: options.transformModules,
});
}
else if (javaScriptMimeTypes.includes(contentType)) {
transformed = polymer_build_1.jsTransform(body, {
compile: options.compileTarget,
transformModulesToAmd: options.transformModules ? 'auto' : false,
moduleResolution,
filePath: filePath,
isComponentRequest,
packageName,
componentDir,
rootDir,
});
}
else {
transformed = body;
}
exports.babelCompileCache.set(cacheKey, transformed);
return transformed;
},
});
}
exports.babelCompile = babelCompile;
//# sourceMappingURL=compile-middleware.js.map
;