diff --git a/package.json b/package.json index cf7d25a..f98780d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vitescv", - "version": "2.0.3", + "version": "2.1.0", "type": "module", "packageManager": "pnpm@8.5.0", "description": "A cli tool for vite & vue2.7", @@ -33,7 +33,6 @@ ], "dependencies": { "@rollup/plugin-commonjs": "^25.0.7", - "@rollup/plugin-node-resolve": "^15.2.3", "@vitejs/plugin-legacy": "^5.2.0", "@vitejs/plugin-vue2": "^2.3.1", "acorn": "^8.11.3", @@ -45,7 +44,6 @@ "minimatch": "^5.1.6", "sass": "~1.32.13", "terser": "^5.26.0", - "unplugin": "^1.6.0", "unplugin-auto-import": "^0.15.3", "unplugin-vue-components": "^0.26.0", "vite": "^5.0.11", diff --git a/src/app.js b/src/app.js index 8cd6bca..c572e4b 100644 --- a/src/app.js +++ b/src/app.js @@ -2,7 +2,7 @@ import Vue from 'vue' import AppComponent from "./App.vue" -import initModules from "$/modules/index.js" +import initModules from "@cache/modules/index.js" import createRouter from './router.js' //@Const 钩子名称 const HookStatus = { diff --git a/src/moduleLib.js b/src/moduleLib.js index a405129..71f737c 100644 --- a/src/moduleLib.js +++ b/src/moduleLib.js @@ -3,7 +3,6 @@ import {pathToFileURL} from "url" import {normalizePath} from "vite" import { dirname,resolve,join} from "path" import { existsSync,writeFileSync,mkdirSync,readFileSync} from "fs" -import { createUnplugin } from 'unplugin' import template from "lodash.template" const require = createRequire(import.meta.url) @@ -32,51 +31,26 @@ export async function initModules(options){ moduleMap.clear() Object.assign(moduleConfigs,{ manualChunks: {}, - linkModulePaths:[], //link等项目外部包的resolve的node_modules目录 - linkModuleRoots:[],//link等项目外部包的项目根目录 external: [], UIDirs: [], UIResolvers:[], - alias: {'vue':require.resolve('vue')}, + alias: { + 'vue':require.resolve('vue'), + 'vue-router':require.resolve('vue-router'), + }, optimizeInclude:[], }) - // 如果是link的vitescv - if(!process.env.__VITESCVROOT.startsWith(process.env.__PROJECTROOT)){ - moduleConfigs.linkModuleRoots.push(process.env.__VITESCVROOT) - moduleConfigs.linkModulePaths.push(resolve(process.env.__VITESCVROOT,'node_modules')) - } for (let moduleName in moduleOptions) { - let moduleIndex = normalizePath(require.resolve(moduleName,{ - paths:[process.env.__PROJECTROOT] - })) - let isPackage = !existsSync(resolve(process.env.__PROJECTROOT,moduleName)) //是否安装外部的包,而不是内部文件 - let isLink = isPackage && !moduleIndex.startsWith(process.env.__PROJECTROOT) //是否用npm link安装的项目外部测试包 - if(!moduleIndex){ - console.error(`[vitescv] [${moduleName}] not exit`) - continue - } try{ - let sourceDir = getModuleRootPathByIndex(moduleIndex,moduleName,isPackage,isLink) - let idx = moduleMap.size - let dstName = `module-${idx}.runtime.js` - let moduleInfo = { - idx, - origin:moduleName, - option: moduleOptions[moduleName]||{}, - sourceDir, - source:moduleIndex, - dstName, - isPackage, - } - moduleMap.set(moduleIndex,moduleInfo) - - moduleConfigs.linkModuleRoots.push(sourceDir) + let moduleInfo = generalModuleInfo(moduleName,moduleOptions[moduleName]) + // console.log(moduleInfo) + // package.json alias + getDepsAlias(moduleInfo) // module index.js - let moduleSourceCode = readFileSync(moduleIndex).toString() - transformModuleSource(moduleIndex,moduleSourceCode) - - //config.js + let moduleSourceCode = readFileSync(moduleInfo.source).toString() + transformModuleSource(moduleInfo.source,moduleSourceCode) + // config.js let configFile = pathToFileURL(join(moduleInfo.sourceDir,'config.js')) // console.log(configFile) if(existsSync(configFile)){ @@ -87,10 +61,6 @@ export async function initModules(options){ return null }) } - // link的时候要把外部包的地址加到reslove的paths里去 - if(moduleInfo.isPackage && !moduleInfo.source.startsWith(process.env.__PROJECTROOT)){ - moduleConfigs.linkModulePaths.push(join(moduleInfo.sourceDir,'node_modules')) - } }catch(e){ console.debug(e) } @@ -200,21 +170,87 @@ function transformModuleSource(id,code){ } } -// 获取模块的根目录 -function getModuleRootPathByIndex(moduleIndex,moduleName,isPackage,isLink){ - let dir = dirname(moduleIndex) - if(!isPackage){ - return dir +// 获取并处理模块的信息 +function generalModuleInfo(moduleName,moduleOption){ + let moduleIndex = normalizePath(require.resolve(moduleName,{ + paths:[process.env.__PROJECTROOT] + })) + if(!moduleIndex){ + console.error(`[vitescv] [${moduleName}] not exit`) + return + } + let idx = moduleMap.size + let dstName = `module-${idx}.runtime.js` + + let sourceDir = dirname(moduleIndex) + let isPackage = existsSync(join(sourceDir,'package.json')) //是否安装外部的包,而不是内部文件 + let isLink = isPackage && !moduleIndex.startsWith(process.env.__PROJECTROOT) //是否用npm link安装的项目外部测试包 + + const moduleInfo = { + idx, + origin:moduleName, + option: moduleOption||{}, + sourceDir, + source:moduleIndex, + dstName, + isPackage, + isLink + } + moduleMap.set(moduleInfo.source,moduleInfo) + return moduleInfo +} + +// 处理依赖为alias +function getDepsAlias(moduleInfo){ + if(!moduleInfo.isPackage){ + return } + const alias = {} + try{ + const json = readFileSync(join(moduleInfo.sourceDir,'package.json')).toString() + const packages = JSON.parse(json) + for (const dep in packages.dependencies) { + const depSource = require.resolve(dep,{ + paths:getPackageNodemodulePaths(moduleInfo.source) + }) + alias[dep] = getDepSourceDir(dep,depSource) + } + Object.assign(moduleConfigs.alias,alias) + }catch(e){ + } +} + +// @vitescv/pinia /Volumes/data/MyModules/vitescvclidemo/node_modules/.pnpm/@vitescv+pinia@1.0.5_vue@2.7.16/node_modules/@vitescv/pinia/index.js +// @vitescv/elementui /Volumes/data/MyModules/vitescv/packages/elementui/index.js +function getPackageNodemodulePaths(moduleIndex){ + if(moduleIndex.startsWith(process.env.__PROJECTROOT)){ + return [ + join(process.env.__PROJECTROOT,'node_modules'), + join(process.env.__PROJECTROOT,'node_modules/.pnpm/node_modules') + ] + } + let dir = dirname(moduleIndex) if(dir){ - if(isLink){ - if(!existsSync(resolve(dir,'package.json'))){ - return getModuleRootPathByIndex(dir,moduleName,isPackage,isLink) + if(!existsSync(resolve(dir,'node_modules'))){ + return getPackageNodemodulePaths(dir) + }else{ + return [ + join(dir,'node_modules'), + join(dir,'node_modules/.pnpm/node_modules') + ] } - }else if(!dir.endsWith(moduleName)){ - return getModuleRootPathByIndex(dir,moduleName,isPackage,isLink) + } + return [] +} + +// 获取某个依赖的根目录,因为有可能会引用该依赖下其他文件所以要去根目录而不是入口文件 +function getDepSourceDir(depName,fpath){ + let dir = dirname(fpath) + if(dir){ + if(dir.endsWith(depName)){ + return dir } - return dir + return getDepSourceDir(depName,dir) } return null } \ No newline at end of file diff --git a/src/router.js b/src/router.js index fcb61c4..f5ebd46 100644 --- a/src/router.js +++ b/src/router.js @@ -3,7 +3,7 @@ */ import Vue from 'vue' import VueRouter from "vue-router" -import getRoutes,{page404} from "$/routes.runtime.js" +import getRoutes,{page404} from "@cache/routes.runtime.js" // 3.1开始 Vue.use(VueRouter) export default function createRouter () { diff --git a/tpl/config.js b/tpl/config.js index 9ca0e1b..3e36854 100644 --- a/tpl/config.js +++ b/tpl/config.js @@ -11,16 +11,18 @@ export default { // targets: ['IE>=11'], // additionalLegacyPolyfills:['regenerator-runtime/runtime'], // } + // 是否禁止访问项目之外的文件fs.strict + fsStrict:false, /****************** 自定义部分 *******************/ modules:{}, - //打包时强制外部化的库 + // 打包时强制外部化的库 external:[], - //404页面 + // 404页面 page404:'/404', - //路由动态加载时的loading组件,AppLoading 预设 + // 路由动态加载时的loading组件,AppLoading 预设 // componentLoading:'@/view/components/loading.vue', - //路由动态加载错误时显示组件,AppError 预设 + // 路由动态加载错误时显示组件,AppError 预设 // componentError:'@/view/components/xx', - //路由页面显示组件,AppView 预设 + // 路由页面显示组件,AppView 预设 // compomentRouteView:'@/view/components/xx', } \ No newline at end of file diff --git a/vite.config.js b/vite.config.js index 17473f7..172216d 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,6 +1,5 @@ import { resolve} from "path" import { splitVendorChunkPlugin,defineConfig,searchForWorkspaceRoot} from 'vite' -import {nodeResolve} from "@rollup/plugin-node-resolve" import legacy from '@vitejs/plugin-legacy' import vue from '@vitejs/plugin-vue2' import Components from 'unplugin-vue-components/vite' @@ -20,11 +19,6 @@ export default function(userConfig){ const isProduction = mode == "production" // console.log(moduleConfigs) - // const moduleChunks = Object.assign({ - // 'vue': ['vue'], - // // 'vrouter': ['vue-router','virtual:router-routes'], - // // 'vmodules': ['virtual:modules','virtual:router-routes'], - // },Config.manualChunks) return { //💡 项目根目录 root:process.env.__PROJECTCACHEROOT, @@ -42,23 +36,15 @@ export default function(userConfig){ resolve: { alias: Object.assign({ '@': process.env.__PROJECTROOT, - '$': process.env.__PROJECTCACHEROOT, + '@cache': process.env.__PROJECTCACHEROOT, '@@vitescv': process.env.__VITESCVROOT, },Config.alias), preserveSymlinks:false, - dedupe:["vue"] + dedupe:["vue","vue-router"] }, plugins: [ Config.legacy&&legacy(Config.legacy), // Inspect(), - nodeResolve({ - preserveSymlinks:false, - // pnpm的话都在node_modules/.pnpm/node_modules下面 - modulePaths:[ - 'node_modules', - 'node_modules/.pnpm/node_modules', - ].concat(Config.linkModulePaths), - }), //💡 2.9之前manualChunks默认的策略是将 chunk 分割为 index 和 vendor,之后要手动启动 splitVendorChunkPlugin(), vueOptions([{ @@ -156,8 +142,8 @@ export default function(userConfig){ // entries:[], //💡 默认情况下,不在 node_modules 中的,链接的包不会被预构建。使用此选项可强制预构建链接的包。 include:Config.optimizeInclude, - // 💡 排除的预构建,vitescv/app包含虚拟模块,预构建的时候并不存在,会报错 - // exclude:[], //npm link安装的时候不报错,正常里面引用的虚拟模块报错 + // 💡 排除的预构建,里面包含的routes和modules不能被预构建 + exclude:["vitescv/app"], //💡 设置为 true 可以强制依赖预构建,而忽略之前已经缓存过的、已经优化过的依赖。 force:false, // 只有development的时候才使用兼容插件来处理,因为prodction的时候会走rollup的unpluginvModules.vite 会冲突 @@ -184,10 +170,7 @@ export default function(userConfig){ interval: 200, }, fs: { - allow: [ - // search up for workspace root - searchForWorkspaceRoot(process.env.__PROJECTROOT), - ].concat(Config.linkModuleRoots) + strict:!!Config.fsStrict, }, }, }