UNPKG

@farmfe/core

Version:

Farm is a extremely fast web build tool written in Rust. Farm can start a project in milliseconds and perform HMR within 10ms, making it much faster than similar tools like webpack and vite.

371 lines 12 kB
import path from 'node:path'; // import path from 'node:path'; import * as querystring from 'node:querystring'; import fse from 'fs-extra'; import { VITE_ADAPTER_VIRTUAL_MODULE } from './constants.js'; export function convertEnforceToPriority(value) { const defaultPriority = 100; const enforceToPriority = { pre: 101, post: 98 }; return enforceToPriority[value] !== undefined ? enforceToPriority[value] : defaultPriority; } export function convertWatchEventChange(value) { const watchEventChange = { Added: 'create', Updated: 'update', Removed: 'delete' }; return watchEventChange[value]; } export function getContentValue(content) { return encodeStr(typeof content === 'string' ? content : content.code); } export function isString(variable) { return typeof variable === 'string'; } export function isObject(variable) { return typeof variable === 'object' && variable !== null; } export function customParseQueryString(url) { if (!url) { return []; } const queryString = url.split('?')[1]; const parsedParams = querystring.parse(queryString); const paramsArray = []; for (const key in parsedParams) { paramsArray.push([key, parsedParams[key]]); } return paramsArray; } export const VITE_PLUGIN_DEFAULT_MODULE_TYPE = 'VITE_PLUGIN_DEFAULT_MODULE_TYPE'; export const CSS_LANGS_RES = [ [/\.(less)(?:$|\?)/, 'less'], [/\.(scss|sass)(?:$|\?)/, 'sass'], [/\.(styl|stylus)(?:$|\?)/, 'stylus'], [/\.(css)(?:$|\?)/, 'css'] ]; export const JS_LANGS_RES = [ [/\.(js|mjs|cjs|)(?:$|\?)/, 'js'], // jsx [/\.(jsx)(?:$|\?)/, 'jsx'], // ts [/\.(ts|cts|mts)(?:$|\?)/, 'ts'], // tsx [/\.(tsx)(?:$|\?)/, 'tsx'] ]; export const DEFAULT_FILTERS = ['!node_modules']; // farm css modules query export const FARM_CSS_MODULES_SUFFIX = /(?:\?|&)farm_css_modules/; export const stringifyQuery = (query) => { if (!query.length) { return ''; } let queryStr = ''; for (const [key, value] of query) { queryStr += `${key}${value ? `=${value}` : ''}&`; } return `${queryStr.slice(0, -1)}`; }; export function formatId(id, query) { // remove the adapter internal virtual module flag if (isStartAdapterVirtualModule(id)) { id = id?.replace(VITE_ADAPTER_VIRTUAL_MODULE, ''); } if (!query.length) { return id; } return `${id}?${stringifyQuery(query)}`; } // determine if it is the adapter's internal virtual module export function isStartAdapterVirtualModule(id) { return id?.startsWith(VITE_ADAPTER_VIRTUAL_MODULE); } export function isStartsWithSlash(str) { return str?.startsWith('/'); } export function addAdapterVirtualModuleFlag(id) { return VITE_ADAPTER_VIRTUAL_MODULE + id; } export function normalizeAdapterVirtualModule(id) { const path = removeQuery(id); // If resolveIdResult is a path starting with / and the file at that path does not exist // then it is considered an internal virtual module if (isStartsWithSlash(path) && !fse.pathExistsSync(path)) return addAdapterVirtualModuleFlag(id); return id; } // normalize path for windows the same as Vite export function normalizePath(p) { return path.posix.normalize(process.platform === 'win32' ? p.replace(/\\/g, '/') : p); } export const removeQuery = (path) => { const queryIndex = path.indexOf('?'); if (queryIndex !== -1) { return path.slice(0, queryIndex); } return revertNormalizePath(path.concat('')); }; export function revertNormalizePath(p) { return process.platform === 'win32' ? p.replace(/\//g, '\\') : p; } export function getCssModuleType(id) { for (const [reg, lang] of CSS_LANGS_RES) { if (reg.test(id)) { return lang; } } return null; } export function getJsModuleType(id) { for (const [reg, lang] of JS_LANGS_RES) { if (reg.test(id)) { return lang; } } return null; } export function formatLoadModuleType(id) { const cssModuleType = getCssModuleType(id); if (cssModuleType) { return cssModuleType; } const jsModuleType = getJsModuleType(id); if (jsModuleType) { return jsModuleType; } return 'js'; } export function formatTransformModuleType(id) { return formatLoadModuleType(id); } // normalize invalid characters in id, for example: \0 // because characters like \0 have issues when passing to Farm's rust compiler export function encodeStr(str) { return str.replace(/\0/g, '\\0'); } export function decodeStr(str) { return str.replace(/\\0/g, '\0'); } export function deleteUndefinedPropertyDeeply(obj) { if (typeof obj !== 'object') { return; } for (const key in obj) { if (!Object.prototype.hasOwnProperty.call(obj, key)) { continue; } if (Array.isArray(obj[key])) { obj[key] = obj[key].filter((item) => item !== undefined); } else if (obj[key] === undefined) { delete obj[key]; } else if (typeof obj[key] === 'object') { deleteUndefinedPropertyDeeply(obj[key]); } } } export function throwIncompatibleError(pluginName, readingObject, allowedKeys, key) { throw new Error(`Vite plugin '${pluginName}' is not compatible with Farm for now. Because it uses ${readingObject}['${String(key)}'] which is not supported by Farm. Current supported keys are: ${allowedKeys.join(',')}`); } export function transformResourceInfo2RollupRenderedChunk(info) { const { modules, moduleIds, name, data } = info; const { dynamicImports, importedBindings, imports, exports, isDynamicEntry, isEntry, isImplicitEntry } = data; return { dynamicImports, fileName: name, implicitlyLoadedBefore: [], importedBindings, imports, modules: Object.entries(modules).reduce((result, [key, val]) => ({ ...result, [key]: { code: val.renderedContent, renderedLength: val.renderedLength, originalLength: val.originalLength, removedExports: [], renderedExports: [] } }), {}), referencedFiles: [], exports, facadeModuleId: null, isDynamicEntry, isEntry, isImplicitEntry, moduleIds, name, type: 'chunk' }; } export function transformResourceInfo2RollupResource(resource) { // Rollup/Vite only treat js files as chunk if (resource.info && resource.resourceType === 'js') { const source = Buffer.from(resource.bytes).toString('utf-8'); return { ...transformResourceInfo2RollupRenderedChunk(resource.info), type: 'chunk', code: source, name: resource.name, map: undefined, sourcemapFileName: null, preliminaryFileName: resource.origin.value }; } else { return { fileName: resource.name, name: resource.name, needsCodeReference: false, source: Uint8Array.from(resource.bytes), type: 'asset' }; } } export function transformRollupResource2FarmResource(chunk, originResource) { if (chunk.type === 'chunk') { return { ...originResource, bytes: Array.from(Buffer.from(chunk.code)), emitted: originResource.emitted, name: chunk.name }; } else { return { bytes: Array.from(chunk.source), emitted: originResource.emitted, name: chunk.name, origin: originResource.origin, resourceType: originResource.resourceType }; } } // eslint-disable-next-line @typescript-eslint/no-explicit-any const notSupport = (method) => () => { console.warn(`${method} not support`); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const noop = () => void 0; function transformFarmFormatToRollupFormat(config) { if (config.format === 'esm') { return 'es'; } else if (config.format === 'cjs') { if (config.targetEnv === 'node') return 'cjs'; return 'amd'; } } export function transformFarmConfigToRollupNormalizedOutputOptions(config) { return { amd: { autoId: false, define: 'define', forceJsExtensionForImports: false }, assetFileNames: config.output.assetsFilename, chunkFileNames: config.output.filename, compact: Boolean(config.minify), dir: config.output.path, dynamicImportInCjs: true, entryFileNames: config.output.entryFilename, esModule: 'if-default-prop', experimentalMinChunkSize: config?.partialBundling?.targetMinSize || 1, exports: 'auto', extend: false, externalImportAssertions: false, // externalImportAttributes: true, externalLiveBindings: true, format: transformFarmFormatToRollupFormat(config.output), freeze: false, generatedCode: { arrowFunctions: false, constBindings: false, objectShorthand: false, reservedNamesAsProps: true, symbols: false }, globals: {}, hoistTransitiveImports: true, indent: true, inlineDynamicImports: false, manualChunks: {}, minifyInternalExports: true, noConflict: false, paths: {}, plugins: [], preserveModules: false, sourcemap: Boolean(config.sourcemap), sourcemapExcludeSources: false, strict: true, systemNullSetters: true, validate: false, banner: notSupport('banner'), footer: notSupport('footer'), interop: notSupport('interop'), outro: notSupport('outro'), intro: notSupport('intro'), sanitizeFileName: notSupport('sanitizeFileName'), sourcemapIgnoreList: notSupport('sourcemapIgnoreList'), dynamicImportFunction: undefined, experimentalDeepDynamicChunkOptimization: false, file: undefined, name: undefined, namespaceToStringTag: false, preferConst: false, preserveModulesRoot: undefined, sourcemapBaseUrl: undefined, sourcemapFile: undefined, sourcemapFileNames: undefined, sourcemapPathTransform: undefined }; } export function transformFarmConfigToRollupNormalizedInputOptions(config) { return { context: 'undefined', experimentalCacheExpiry: 10, experimentalLogSideEffects: false, input: config.input, logLevel: 'info', makeAbsoluteExternalsRelative: 'ifRelativeSource', maxParallelFileOps: 20, perf: false, plugins: [], preserveEntrySignatures: 'exports-only', preserveSymlinks: false, shimMissingExports: false, strictDeprecations: false, treeshake: config.treeShaking && { moduleSideEffects: () => false, annotations: true, correctVarValueBeforeDeclaration: false, manualPureFunctions: [], propertyReadSideEffects: true, tryCatchDeoptimization: true, unknownGlobalSideEffects: true }, acorn: undefined, acornInjectPlugins: undefined, cache: undefined, external: undefined, inlineDynamicImports: undefined, manualChunks: undefined, maxParallelFileReads: undefined, moduleContext: undefined, onLog: noop, onwarn: noop, preserveModules: undefined }; } export function normalizeFilterPath(path) { if (process.platform === 'win32') { return compatibleWin32Path(path); } return path; } function compatibleWin32Path(path) { return path.replaceAll('/', '\\\\'); } //# sourceMappingURL=utils.js.map