Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asset Manager Sourcemaps #17533

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
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: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,6 @@ node_modules/
#exclude parcel
.parcel-cache

#exclude .map files
*.map

wwwroot
**/Localization/**/*.po
!test/OrchardCore.Tests/Localization/**/*.po
Expand Down
1 change: 1 addition & 0 deletions .scripts/assets-manager/assetGroups.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { glob } from "glob";
import JSON5 from "json5";
import fs from "fs-extra";
import path from "path";
import process from "node:process";

import buildConfig from "./config.mjs";

Expand Down
2 changes: 2 additions & 0 deletions .scripts/assets-manager/build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import { fileURLToPath } from "url";
import parseArgs from "minimist";
import _ from "lodash";
import prettyMilliseconds from 'pretty-ms';
import { Buffer } from 'buffer';
import buildConfig from "./config.mjs";
import clean from "./clean.mjs";
import getAllAssetGroups from "./assetGroups.mjs";
import process from 'node:process';

const startTime = performance.now();

Expand Down
33 changes: 30 additions & 3 deletions .scripts/assets-manager/clean.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import chalk from "chalk";
import path from "path";
import fs from "fs-extra";
import process from "node:process";

export default async function clean(groups) {
console.log(chalk.redBright("Clean task called. This wipes all folders referenced as destinations of all groups. Waiting 3 seconds before starting."));
Expand All @@ -9,25 +10,51 @@ export default async function clean(groups) {
const promises = [];
for (const g of groups) {
if (g.dest) {
if (!g.dest || typeof g.dest !== "string" || !(g.dest.includes("wwwroot") || g.dest.includes("dist"))) {
if (typeof g.dest !== "string" || !(g.dest.includes("wwwroot") || g.dest.includes("dist"))) {
console.log(chalk.red("We only support deleting folders that contain wwwroot or dist"), chalk.gray(g.dest));
throw chalk.red("Error cleaning: ") + chalk.gray(g.dest);
}

promises.push(
fs
await fs
.rm(g.dest, { recursive: true, force: true })
.then(() => console.log(chalk.green("Deleted folder:"), chalk.gray(g.dest)))
.catch((err) => {
console.log(chalk.red("Error deleting folder:"), chalk.gray(g.dest));
throw err;
}),
);
} else {
const scriptFolder = path.resolve(g.basePath + "\\wwwroot\\Scripts");
const styleFolder = path.resolve(g.basePath + "\\wwwroot\\Styles");

console.log(scriptFolder, styleFolder);
if (fs.exists(scriptFolder)) {
console.log("allo 1");
await fs
.rm(scriptFolder, { recursive: true, force: true })
.then(() => console.log(chalk.green("Deleted folder:"), chalk.gray(scriptFolder)))
.catch((err) => {
console.log(chalk.red("Error deleting folder:"), chalk.gray(scriptFolder));
throw err;
});
}

if (fs.exists(styleFolder)) {
console.log("allo 2");
await fs
.rm(styleFolder, { recursive: true, force: true })
.then(() => console.log(chalk.green("Deleted folder:"), chalk.gray(styleFolder)))
.catch((err) => {
console.log(chalk.red("Error deleting folder:"), chalk.gray(styleFolder));
throw err;
});
}
}
}
const parcelCache = path.join(process.cwd(), ".parcel-cache");
promises.push(
fs
await fs
.rm(parcelCache, { recursive: true, force: true })
.then(() => console.log(chalk.green("Deleted folder:"), chalk.gray(parcelCache)))
.catch((err) => {
Expand Down
1 change: 1 addition & 0 deletions .scripts/assets-manager/config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from "path";
import chalk from "chalk";
import { pathToFileURL } from "url";
import process from "node:process";

const isWin = process.platform === "win32";
let pathToFile = path.join(process.cwd(), "build.config.mjs");
Expand Down
23 changes: 12 additions & 11 deletions .scripts/assets-manager/copy.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ import { glob } from "glob";
import JSON5 from "json5";
import chalk from "chalk";
import path from "path";
import process from "node:process";
import { Buffer } from "buffer";

let action = process.argv[2];
const config = JSON5.parse(Buffer.from(process.argv[3], "base64").toString("utf-8"));

let dest = config.dest;
let fileExtension = config.source.split(".").pop();

if (config.dest == undefined) {
if (config.tags.includes("js") || fileExtension == "js") {
dest = config.basePath + "/wwwroot/Scripts/";
config.dest = config.basePath + "/wwwroot/Scripts/";
} else if (config.tags.includes("css") || fileExtension == "css") {
dest = config.basePath + "/wwwroot/Styles/";
config.dest = config.basePath + "/wwwroot/Styles/";
}
}

Expand All @@ -30,17 +31,17 @@ glob(config.source).then((files) => {
return;
}

const destExists = fs.existsSync(dest);
const destExists = fs.existsSync(config.dest);

if (destExists) {
const stats = fs.lstatSync(dest);
const stats = fs.lstatSync(config.dest);
if (!stats.isDirectory()) {
console.log(chalk.red("Destination is not a directory"));
console.log("Files:", files);
console.log("Destination:", dest);
console.log("Destination:", config.dest);
return;
}
console.log(chalk.yellow(`Destination ${dest} already exists, files may be overwritten`));
console.log(chalk.yellow(`Destination ${config.dest} already exists, files may be overwritten`));
}

let baseFolder;
Expand All @@ -49,7 +50,7 @@ glob(config.source).then((files) => {
baseFolder = config.source.substring(0, config.source.indexOf("**"));
}

files.forEach((file) => {
files.forEach(async (file) => {
file = file.replace(/\\/g, "/");
let relativePath;
if (baseFolder) {
Expand All @@ -58,14 +59,14 @@ glob(config.source).then((files) => {
relativePath = path.basename(file);
}

const target = path.join(dest, relativePath);
const target = path.join(config.dest, relativePath);

if (action === "dry-run") {
console.log(`Dry run (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(target));
} else {
fs.stat(file).then((stat) => {
await fs.stat(file).then(async (stat) => {
if (!stat.isDirectory()) {
fs.copy(file, target)
await fs.copy(file, target)
.then(() => console.log(`Copied (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(target)))
.catch((err) => {
console.log(`${chalk.red("Error copying")} (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(target), chalk.red(err));
Expand Down
77 changes: 38 additions & 39 deletions .scripts/assets-manager/min.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { transform } from "lightningcss";
import postcss from "postcss";
import postcssRTLCSS from "postcss-rtlcss";
import { Mode, Source } from "postcss-rtlcss/options";
import process from "node:process";
import { Buffer } from "buffer";

let action = process.argv[2];
let mode = action === "build" ? "production" : "development";
Expand Down Expand Up @@ -78,37 +80,42 @@ glob(config.source).then((files) => {
if (fileInfo.ext === ".js") {
let reader = await fs.readFile(file, "utf8");
Copy link
Contributor Author

@Skrypt Skrypt Feb 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the issue I think is that fs on windows will read this file with \r\n in it and on linux it will read it with \n
Then when it creates the .map file it generates different mappings hash because that file length is longer on Windows making it fall on more lines making the hashes to differ.


swc.minify(reader, {
compress: true,
sourceMap: mode === "development",
}).then((output) => {
const minifiedTarget = path.join(dest, path.parse(target).name + ".min.js");
fs.outputFile(minifiedTarget, output.code);
console.log(`Minified (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(minifiedTarget));
await swc
.minify(reader.replace(/(\r?\n|\r)/gm, "\n"), {
compress: true,
sourceMap: mode === "production",
})
.then((output) => {
const minifiedTarget = path.join(dest, path.parse(target).name + ".min.js");

fs.outputFile(minifiedTarget, output.code);
console.log(`Minified (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(minifiedTarget));

if (mode === "production" && output.map) {
const mappedTarget = path.join(dest, path.parse(target).name + ".map");
let normalized = output.map.replace(/(?:\\[rn])+/g, "\\n");
fs.outputFile(mappedTarget, normalized + "\n");
console.log(`Mapped (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(mappedTarget));
}
});

if (mode === "development" && output.map) {
const mappedTarget = path.join(dest, path.parse(target).name + ".map");
const normalized = output.map.replace(/(?:\\[rn])+/g, "\\n");
fs.outputFile(mappedTarget, normalized + "\n");
console.log(`Mapped (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(mappedTarget));
}
});
let sourceFile = reader.toString().replace(/(?:\\[rn])+/g, "\\n");

// Remove last line from sourceFile if it is a newline
let sourceLines = sourceFile.split("\n");
if (sourceLines[sourceLines.length - 1] === "") {
sourceLines.pop();
}
sourceFile = sourceLines.join("\n");
sourceFile = sourceFile + "\n";

fs.exists(target).then((exists) => {
if (!exists) {
fs.copy(file, target)
.then(() => console.log(`Copied (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(target)))
.catch((err) => {
console.log(
`${chalk.red("Error copying")} (${chalk.gray("from")}, ${chalk.cyan("to")})`,
chalk.gray(file),
chalk.cyan(target),
chalk.red(err),
);
throw err;
});
}
});
await fs
.outputFile(target, sourceFile)
.then(() => console.log(`Copied (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(target)))
.catch((err) => {
console.log(`${chalk.red("Error copying")} (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(target), chalk.red(err));
throw err;
});
} else if (fileInfo.ext === ".css") {
let reader = await fs.readFile(file, "utf8");

Expand Down Expand Up @@ -138,24 +145,16 @@ glob(config.source).then((files) => {
throw err;
});

let { code, map } = transform({
let { code } = transform({
code: Buffer.from(reader),
minify: true,
sourceMap: mode === "development",
minify: true
});

if (code) {
const minifiedTarget = path.join(dest, path.parse(target).name + ".min.css");
await fs.outputFile(minifiedTarget, code.toString());
console.log(`Minified (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(minifiedTarget));
}

if (mode === "development" && map) {
const mappedTarget = path.join(dest, path.parse(target).name + ".map");
const normalized = map.toString().replace(/(?:\\[rn])+/g, "\\n");
await fs.outputFile(mappedTarget, normalized + "\n");
console.log(`Mapped (${chalk.gray("from")}, ${chalk.cyan("to")})`, chalk.gray(file), chalk.cyan(mappedTarget));
}
} else {
console.log("Trying to minify a file with an extension that is not allowed.");
}
Expand Down
8 changes: 4 additions & 4 deletions .scripts/assets-manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@parcel/transformer-sass": "2.13.3",
"@parcel/transformer-vue": "2.13.3",
"@parcel/utils": "2.13.3",
"@swc/core": "1.10.16",
"@swc/core": "1.11.4",
"@vitejs/plugin-vue": "^5.2.1",
"chalk": "^5.2.0",
"chokidar": "^4.0.3",
Expand All @@ -36,11 +36,11 @@
"parcel": "2.13.3",
"parcel-config-vue2": "^0.1.3",
"parcel-transformer-vue2": "^0.1.7",
"postcss": "8.5.2",
"postcss": "8.5.3",
"postcss-rtlcss": "5.6.0",
"pretty-ms": "9.2.0",
"sass": "^1.84.0",
"vite": "^6.1.0",
"sass": "^1.85.1",
"vite": "^6.2.0",
"vue": "^3.5.13",
"vue-hot-reload-api": "^2.3.4",
"webpack": "^5.98.0",
Expand Down
Loading
Loading