1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-22 15:06:54 -05:00
denoland-deno/rollup.config.js

231 lines
7.8 KiB
JavaScript

// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
// @ts-check
import * as fs from "fs";
import path from "path";
import alias from "rollup-plugin-alias";
import { plugin as analyze } from "rollup-plugin-analyzer";
import commonjs from "rollup-plugin-commonjs";
import globals from "rollup-plugin-node-globals";
import nodeResolve from "rollup-plugin-node-resolve";
import typescriptPlugin from "rollup-plugin-typescript2";
import { createFilter } from "rollup-pluginutils";
import replace from "rollup-plugin-replace";
import typescript from "typescript";
const mockPath = path.resolve(__dirname, "js/mock_builtin.js");
const tsconfig = path.resolve(__dirname, "tsconfig.json");
const typescriptPath = path.resolve(
__dirname,
"third_party/node_modules/typescript/lib/typescript.js"
);
// We will allow generated modules to be resolvable by TypeScript based on
// the current build path
const tsconfigOverride = {
compilerOptions: {
paths: {
"*": ["*", path.resolve("*")]
}
}
};
const archNodeToDeno = {
x64: "x64"
};
const osNodeToDeno = {
win32: "win",
darwin: "mac",
linux: "linux"
};
function generateDepFile({ outputFile, sourceFiles = [], configFiles = [] }) {
let timestamp = new Date();
// Save the depfile just before the node process exits.
process.once("beforeExit", () =>
writeDepFile({ outputFile, sourceFiles, configFiles, timestamp })
);
return {
name: "depfile",
load(sourceFile) {
// The 'globals' plugin adds generated files that don't exist on disk.
// Don't add them to the depfile.
if (/^[0-9a-f]{30}$/.test(sourceFile)) {
return;
}
sourceFiles.push(sourceFile);
// Remember the time stamp that we last resolved a dependency.
// We'll set the last modified time of the depfile to that.
timestamp = new Date();
}
};
}
function writeDepFile({ outputFile, sourceFiles, configFiles, timestamp }) {
const buildDir = process.cwd();
const outputDir = path.dirname(outputFile);
// Assert that the discovered bundle inputs are files that exist on disk.
sourceFiles.forEach(f => fs.accessSync(f));
// Since we also want to rebuild the bundle if rollup configuration or the the
// tooling changes (e.g. when typescript is updated), add the currently loaded
// node.js modules to the list of dependencies.
let inputs = [...sourceFiles, ...configFiles, ...Object.keys(require.cache)];
// Deduplicate the list of inputs.
inputs = Array.from(new Set(inputs.map(f => path.resolve(f))));
// Turn filenames into relative paths and format/escape them for a Makefile.
inputs = inputs.map(formatPath);
// Build a list of output filenames and normalize those too.
const depFile = path.join(
outputDir,
path.basename(outputFile, path.extname(outputFile)) + ".d"
);
const outputs = [outputFile, depFile].map(formatPath);
// Generate depfile contents.
const depFileContent = [
...outputs.map(filename => `${filename}: ` + inputs.join(" ") + "\n\n"),
...inputs.map(filename => `${filename}:\n`)
].join("");
// Since we're writing the depfile when node's "beforeExit" hook triggers,
// it's getting written _after_ the regular outputs are saved to disk.
// Therefore, after writing the depfile, reset its timestamps to when we last
// discovered a dependency, which was certainly before the bundle was built.
fs.writeFileSync(depFile, depFileContent);
fs.utimesSync(depFile, timestamp, timestamp);
// Renders path to make it suitable for a depfile.
function formatPath(filename) {
// Make the path relative to the root build directory.
filename = path.relative(buildDir, filename);
// Use forward slashes on Windows.
if (process.platform === "win32") {
filename = filename.replace(/\\/g, "/");
}
// Escape spaces with a backslash. This is what rust and clang do too.
filename = filename.replace(/ /g, "\\ ");
return filename;
}
}
export default function makeConfig(commandOptions) {
return {
output: {
format: "iife",
name: "denoMain",
sourcemap: true,
sourcemapExcludeSources: true
},
plugins: [
// inject build and version info
replace({
ROLLUP_REPLACE_TS_VERSION: typescript.version,
ROLLUP_REPLACE_ARCH: archNodeToDeno[process.arch],
ROLLUP_REPLACE_OS: osNodeToDeno[process.platform]
}),
// would prefer to use `rollup-plugin-virtual` to inject the empty module, but there
// is an issue with `rollup-plugin-commonjs` which causes errors when using the
// virtual plugin (see: rollup/rollup-plugin-commonjs#315), this means we have to use
// a physical module to substitute
alias({
fs: mockPath,
path: mockPath,
os: mockPath,
crypto: mockPath,
buffer: mockPath,
module: mockPath
}),
// Allows rollup to resolve modules based on Node.js resolution
nodeResolve(),
// Allows rollup to import CommonJS modules
commonjs({
namedExports: {
// Static analysis of `typescript.js` does detect the exports properly, therefore
// rollup requires them to be explicitly defined to make them available in the
// bundle
[typescriptPath]: [
"convertCompilerOptionsFromJson",
"createLanguageService",
"createProgram",
"createSourceFile",
"getPreEmitDiagnostics",
"formatDiagnostics",
"formatDiagnosticsWithColorAndContext",
"parseConfigFileTextToJson",
"version",
"CompilerHost",
"DiagnosticCategory",
"Extension",
"ModuleKind",
"ScriptKind",
"ScriptSnapshot",
"ScriptTarget"
]
}
}),
typescriptPlugin({
// The build script is invoked from `out/:target` so passing an absolute file path is needed
tsconfig,
// This provides any overrides to the `tsconfig.json` that are needed to bundle
tsconfigOverride,
// This provides the locally configured version of TypeScript instead of the plugins
// default version
typescript,
// By default, the include path only includes the cwd and below, need to include the root of the project
// and build path to be passed to this plugin. This is different front tsconfig.json include
include: ["*.ts", `${__dirname}/**/*.ts`, `${process.cwd()}/**/*.ts`],
// d.ts files are not bundled and by default like include, it only includes the cwd and below
exclude: [
"*.d.ts",
`${__dirname}/**/*.d.ts`,
`${process.cwd()}/**/*.d.ts`
]
}),
// Provide some concise information about the bundle
analyze({
skipFormatted: true,
onAnalysis({
bundleSize,
bundleOrigSize,
bundleReduction,
moduleCount
}) {
if (!commandOptions.silent) {
console.log(
`Bundle size: ${Math.round((bundleSize / 1000000) * 100) / 100}Mb`
);
console.log(
`Original size: ${Math.round((bundleOrigSize / 1000000) * 100) /
100}Mb`
);
console.log(`Reduction: ${bundleReduction}%`);
console.log(`Module count: ${moduleCount}`);
}
}
}),
// source-map-support, which is required by TypeScript to support source maps, requires Node.js Buffer
// implementation. This needs to come at the end of the plugins because of the impact it has on
// the existing runtime environment, which breaks other plugins and features of the bundler.
globals(),
generateDepFile({
outputFile: commandOptions.o,
configFiles: [commandOptions.c, tsconfig]
})
]
};
}