Skip to content

Commit

Permalink
fixed moduels hot reload . rebuild
Browse files Browse the repository at this point in the history
  • Loading branch information
cczw2010 committed Feb 14, 2024
1 parent ddb77e1 commit 5c46ac7
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 84 deletions.
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vitescv",
"version": "2.0.3",
"version": "2.1.0",
"type": "module",
"packageManager": "[email protected]",
"description": "A cli tool for vite & vue2.7",
Expand Down Expand Up @@ -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",
Expand All @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
140 changes: 88 additions & 52 deletions src/moduleLib.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)){
Expand All @@ -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)
}
Expand Down Expand Up @@ -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/@[email protected][email protected]/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
}
2 changes: 1 addition & 1 deletion src/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand Down
12 changes: 7 additions & 5 deletions tpl/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
}
27 changes: 5 additions & 22 deletions vite.config.js
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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,
Expand All @@ -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([{
Expand Down Expand Up @@ -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 会冲突
Expand All @@ -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,
},
},
}
Expand Down

0 comments on commit 5c46ac7

Please sign in to comment.