跳到主要内容

Vue2.0 源码开发环境

2023年03月04日
柏拉文
越努力,越幸运

Vue.js 源码是基于 Rollup 构建的,它的构建相关配置都在 scripts 目录下。

一、初始化


通过yarn init -y 初始化 package.json 文件

yarn init -y 

二、配置命令


package.json 中配置rollup打包命令

"scripts": {
"build": "node scripts/build.js"
}

三、tsconfig.json


通过tsc --init 初始化 tsconfig.json 文件, 并配置如下

{
"compilerOptions": {
"strict": true,
"newLine": "LF",
"allowJs": true,
"jsx": "preserve",
"skipLibCheck": true,
"moduleResolution": "node",
"forceConsistentCasingInFileNames": true,
},
}

四、编写 scripts/build.js


const Fs = require("fs");
const Path = require("path");
const zlib = require('zlib');
const rollup = require("rollup");
const terser = require("terser");

if (!Fs.existsSync("dist")) {
Fs.mkdirSync("dist");
}

let builds = require("./config").getAllBuilds();

build(builds);

function build(builds) {
let built = 0;
const total = builds.length;
const next = () => {
buildEntry(builds[built])
.then(() => {
built++;
if (built < total) {
next();
}
})
.catch(logError);
};

next();
}

function buildEntry(config) {
const output = config.output;
const { file, banner } = output;
const isProd = /(min|prod)\.js$/.test(file);
return rollup
.rollup(config)
.then((bundle) => bundle.generate(output))
.then(async ({ output: [{ code }] }) => {
if (isProd) {
const { code: minifiedCode } = await terser.minify(code, {
toplevel: true,
compress: {
pure_funcs: ["makeMap"],
},
format: {
ascii_only: true,
},
});
const minified = (banner ? banner + "\n" : "") + minifiedCode;
return write(file, minified, true);
} else {
return write(file, code);
}
});
}

function write(dest, code, zip) {
return new Promise((resolve, reject) => {
function report(extra) {
console.log(
blue(Path.relative(process.cwd(), dest)) +
" " +
getSize(code) +
(extra || "")
);
resolve();
}

if (!Fs.existsSync(Path.dirname(dest))) {
Fs.mkdirSync(Path.dirname(dest), { recursive: true });
}
Fs.writeFile(dest, code, (err) => {
if (err) return reject(err);
if (zip) {
zlib.gzip(code, (err, zipped) => {
if (err) return reject(err);
report(" (gzipped: " + getSize(zipped) + ")");
});
} else {
report();
}
});
});
}

function getSize(code) {
return (code.length / 1024).toFixed(2) + "kb";
}

function logError(e) {
console.log(e);
}

function blue(str) {
return "\x1b[1m\x1b[34m" + str + "\x1b[39m\x1b[22m";
}

五、编写 scripts/config.js


const path = require("path");
const RollupPluginAlias = require("@rollup/plugin-alias");
const RollupPluginReplace = require("@rollup/plugin-replace");
const RollupPluginTypescript = require("@rollup/plugin-typescript");

const version = process.env.VERSION || require("../package.json").version;

const banner = `/** 学习 Vue.js 2.0 构建过程 version ${version} **/`;

const resolve = (p) => {
return path.resolve(__dirname, "../", p);
};

const builds = {
development: {
entry: resolve("src/index.ts"),
dest: resolve("dist/index.dev.js"),
format: "cjs",
env: "development",
banner,
moduleName: "development",
},
production: {
entry: resolve("src/index.ts"),
dest: resolve("dist/index.prod.js"),
format: "cjs",
env: "production",
banner,
moduleName: "production",
},
};

function genConfig(name) {
const opts = builds[name];
const config = {
input: opts.entry,
external: opts.external,
plugins: [
RollupPluginAlias({
entries: Object.assign({}, opts.alias),
}),
RollupPluginTypescript({
tsconfig: path.resolve(__dirname, "../", "tsconfig.json"),
cacheDir: ".rollup.tscache",
compilerOptions: {
types: ["node"],
target: "es2015",
module: "ESNext",
lib: ["es2015", "esnext", "dom"],
},
include: ["src/*"],
exclude: ["node_modules", "dist"],
}),
].concat(opts.plugins || []),
output: {
file: opts.dest,
format: opts.format,
banner: opts.banner,
name: opts.moduleName,
exports: "auto",
},
onwarn: (msg, warn) => {
if (!/Circular/.test(msg)) {
warn(msg);
}
},
};
const vars = {
__VERSION__: version,
__DEV__: `process.env.NODE_ENV !== 'production'`,
__TEST__: false,
__GLOBAL__: opts.format === "umd" || name.includes("browser"),
};
if (opts.env) {
vars["process.env.NODE_ENV"] = JSON.stringify(opts.env);
vars.__DEV__ = opts.env !== "production";
}
vars.preventAssignment = true;
config.plugins.push(RollupPluginReplace(vars));

Object.defineProperty(config, "_name", {
enumerable: false,
value: name,
});

return config;
}

exports.getAllBuilds = () => Object.keys(builds).map(genConfig);