2023-10-24 09:50:42 +08:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title >
verdaccio 搭建 npm私库
< / title >
< meta name = "description" content = "" >
< meta name = "keywords" content = "" >
< meta name = "author" content = "Mozzie" >
2024-03-15 15:38:52 +08:00
< link rel = "canonical" href = "https://maxshader.com/posts/12085/" >
2023-10-24 09:50:42 +08:00
< link rel = "icon" type = "image/svg" href = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 7h1a2 2 0 0 1 2 2v.5a.5.5 0 0 0 .5.5a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.5.5a.5.5 0 0 0-.5.5v.5a2 2 0 0 1-2 2h-2"></path><path d="M8 7H6a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h1"></path><path d="M12 8l-2 4h3l-2 4"></path></g></svg>' >
2023-12-28 11:27:53 +08:00
< link rel = "stylesheet" href = "/css/b4c95347.css" >
2023-10-24 09:50:42 +08:00
2023-12-25 16:39:03 +08:00
< script > window . i18n = { "tip-status-done" : "完成" , "tip-status-default" : "全部" , "tip-status-todo" : "计划" , "tip-status-doing" : "进行" , "tip-status-other" : "其他" , "text-select" : "选择" , "text-move" : "移动" , "text-esc" : "退出" , "January" : "一月" , "February" : "二月" , "March" : "三月" , "April" : "四月" , "May" : "五月" , "June" : "六月" , "July" : "七月" , "August" : "八月" , "September" : "九月" , "October" : "十月" , "November" : "十一月" , "December" : "十二月" } < / script >
< meta name = "generator" content = "Hexo 7.0.0" > < / head >
2023-10-24 09:50:42 +08:00
< body id = "app" >
2023-12-25 16:39:03 +08:00
< aside id = "aside-box" class = "left-aside" >
< div class = "header" >
2023-10-24 09:50:42 +08:00
2023-12-25 16:39:03 +08:00
< link rel = "stylesheet" href = "/css/61875ce9.css" >
2023-10-24 09:50:42 +08:00
2023-12-25 16:39:03 +08:00
< div class = "profile" >
< a class = "badge" href = "/" >
< span > Hi< / span >
2023-10-24 09:50:42 +08:00
< span > Mozzie< / span >
< / a >
2023-12-25 16:39:03 +08:00
< cosy-tooltip id = "left-aside-button" placement = "right" >
< span slot = "content" >
< span > 显示 / 隐藏 左侧导航< / span >
< cosy-short-key > [< / cosy-short-key >
< / span >
< cosy-icon >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 20 20" >
< g fill = "none" >
< path d = "M16 4c1.104-.019 2 .896 2 2v8a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h12zm1 2a1 1 0 0 0-1-1h-2.995v10H16a1 1 0 0 0 1-1V6zm-4.995 9V5H4.001a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8.004z" fill = "currentColor" > < / path >
< / g >
< / svg >
< / cosy-icon >
< / cosy-tooltip >
2023-10-24 09:50:42 +08:00
< / div >
2023-12-28 11:27:53 +08:00
< script src = "/js/e0a67917.js" > < / script >
2023-10-24 09:50:42 +08:00
2023-12-25 16:39:03 +08:00
2023-10-24 09:50:42 +08:00
2023-12-25 16:39:03 +08:00
< cosy-search id = "post-search" placeholder = "搜索" >
< div slot = "short-key" >
< cosy-short-key > ⌘< / cosy-short-key >
< cosy-short-key > K< / cosy-short-key >
2023-10-24 09:50:42 +08:00
< / div >
2023-12-25 16:39:03 +08:00
< / cosy-search >
2023-10-24 09:50:42 +08:00
< script >
window.algolia = {
appId: "5DTW808BZ8",
SearchOnlyAPIKey: "27845b245efc8a2853cc0bdc7366ea26"
}
< / script >
2023-12-28 11:27:53 +08:00
< script src = "/js/62d6af47.js" > < / script >
2023-10-24 09:50:42 +08:00
2023-12-25 16:39:03 +08:00
< / div >
< div class = "aside-category" >
2023-11-03 14:52:16 +08:00
2023-12-25 16:39:03 +08:00
< link rel = "stylesheet" href = "/css/db04a759.css" >
2023-10-24 09:50:42 +08:00
2023-12-25 16:39:03 +08:00
< nav class = "category-nav cosy-scrollbar" >
< ul > < li data-path = "archives" >
2023-11-10 13:44:10 +08:00
< a href = "/archives" >
2023-12-25 16:39:03 +08:00
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 20 20" > < g fill = "none" > < path d = "M3.5 3A1.5 1.5 0 0 0 2 4.5v4A1.5 1.5 0 0 0 3.5 10h9A1.5 1.5 0 0 0 14 8.5v-4A1.5 1.5 0 0 0 12.5 3h-9zM3 4.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5v-4zm.5 6.5A1.5 1.5 0 0 0 2 12.5v4A1.5 1.5 0 0 0 3.5 18h9a1.5 1.5 0 0 0 1.5-1.5v-4a1.5 1.5 0 0 0-1.5-1.5h-9zM3 12.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5v-4zm14-.063a2.003 2.003 0 0 1-2.5-1.937A2 2 0 0 1 16 8.563a2.005 2.005 0 0 1 1 0a2 2 0 0 1 0 3.874zM16.5 3a.5.5 0 0 1 .5.5v4.041a3.02 3.02 0 0 0-1 0V3.5a.5.5 0 0 1 .5-.5zm0 10.5c-.17 0-.337-.014-.5-.041V17.5a.5.5 0 0 0 1 0v-4.041c-.163.027-.33.041-.5.041z" fill = "currentColor" > < / path > < / g > < / svg >
< div class = "ellipsis" > 归档< / div >
< / a >
< / li > < li data-path = "cosy-roadmap" >
< a href = "/cosy-roadmap" >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 20 20" > < g fill = "none" > < path d = "M9.384 2a1 1 0 0 0-.966.742L4.616 17H2.5a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1h-2.116L11.582 2.742A1 1 0 0 0 10.616 2H9.384zM5.651 17l.8-3H11.5a.5.5 0 0 0 0-1H6.717l.534-2H10.5a.5.5 0 0 0 0-1H7.517l1.867-7h1.232l3.733 14H5.651z" fill = "currentColor" > < / path > < / g > < / svg >
< div class = "ellipsis" > 路线图< / div >
< / a >
< / li > < li data-path = "cosy-resume" >
< a href = "/cosy-resume" >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 20 20" > < g fill = "none" > < path d = "M8.5 4.498a1.5 1.5 0 1 1 3 0a1.5 1.5 0 0 1-3 0zm1.5-2.5a2.5 2.5 0 0 0-2.43 3.086L5.471 4.15a1.761 1.761 0 0 0-2.317.88c-.4.882-.008 1.917.877 2.31L7 8.662v2.287l-1.877 4.645a1.75 1.75 0 0 0 3.245 1.311l1.556-3.849a.073.073 0 0 1 .028-.038a.086.086 0 0 1 .046-.012c.02 0 .035.005.046.012a.074.074 0 0 1 .028.038l1.555 3.849a1.75 1.75 0 0 0 3.245-1.311L13 10.96V8.662l2.968-1.322a1.74 1.74 0 0 0 .877-2.31a1.761 1.761 0 0 0-2.317-.88l-2.097.934a2.5 2.5 0 0 0-2.43-3.086zM4.065 5.444a.761.761 0 0 1 1-.38l3.918 1.744a2.5 2.5 0 0 0 2.034 0l3.918-1.744a.761.761 0 0 1 1 .38a.739.739 0 0 1-.373.983l-2.969 1.321a1 1 0 0 0-.593.914v2.298a1 1 0 0 0 .073.375l1.872 4.633a.75.75 0 0 1-1.39.562l-1.556-3.849c-.364-.9-1.639-.9-2.003 0l-1.555 3.85a.75.75 0 1 1-1.39-.562l1.876-4.646A1 1 0 0 0 8 10.95V8.662a1 1 0 0 0-.593-.914L4.438 6.427a.739.739 0 0 1-.373-.983z" fill = "currentColor" > < / path > < / g > < / svg >
< div class = "ellipsis" > 简历< / div >
< / a >
2023-11-10 13:44:10 +08:00
< / li > < / ul >
2023-12-26 10:59:02 +08:00
< ul > < li class = "active" >
< a href = "/categories/CS/" >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 24 24" > < g fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" > < path d = "M20 4l-2 14.5l-6 2l-6-2L4 4z" > < / path > < path d = "M7.5 8h3v8l-2-1" > < / path > < path d = "M16.5 8H14a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h1.423a.5.5 0 0 1 .495.57L15.5 15.5l-2 .5" > < / path > < / g > < / svg >
2023-11-10 13:51:34 +08:00
< div class = "ellipsis" >
2023-12-26 10:59:02 +08:00
< span > CS< / span >
2023-11-10 13:51:34 +08:00
< / div >
2023-11-10 13:44:10 +08:00
< / a >
< / li > < li class = "" >
2023-12-26 10:59:02 +08:00
< a href = "/categories/EQ/" >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 24 24" > < g fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" > < path d = "M5.636 5.636a9 9 0 0 1 13.397.747L13.414 12l5.619 5.617A9 9 0 1 1 5.636 5.636z" > < / path > < circle cx = "11.5" cy = "7.5" r = "1" fill = "currentColor" > < / circle > < / g > < / svg >
2023-11-10 13:51:34 +08:00
< div class = "ellipsis" >
2023-12-26 10:59:02 +08:00
< span > EQ< / span >
2023-11-10 13:51:34 +08:00
< / div >
2023-11-10 13:44:10 +08:00
< / a >
< / li > < li class = "" >
< a href = "/categories/Hexo/" >
2023-11-10 13:51:34 +08:00
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 24 24" > < g fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" > < path d = "M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1" > < / path > < path d = "M8 16h8" > < / path > < path d = "M8.322 12.582l7.956.836" > < / path > < path d = "M8.787 9.168l7.826 1.664" > < / path > < path d = "M10.096 5.764l7.608 2.472" > < / path > < / g > < / svg >
< div class = "ellipsis" >
< span > Hexo< / span >
< / div >
2023-11-10 13:44:10 +08:00
< / a >
2023-11-21 13:49:17 +08:00
< / li > < li class = "" >
2023-12-26 10:59:02 +08:00
< a href = "/categories/%E8%87%AA%E5%AA%92%E4%BD%93/" >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 24 24" > < path d = "M9 12a4 4 0 1 0 4 4V4a5 5 0 0 0 5 5" fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" > < / path > < / svg >
2023-11-21 13:49:17 +08:00
< div class = "ellipsis" >
2023-12-26 10:59:02 +08:00
< span > 自媒体< / span >
2023-11-21 13:49:17 +08:00
< / div >
< / a >
2023-11-11 18:48:29 +08:00
< / li > < li class = "" >
2023-12-26 10:59:02 +08:00
< a href = "/categories/%E8%AF%BB%E4%B9%A6/" >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 20 20" > < g fill = "none" > < path d = "M4 16V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v11a1 1 0 0 1-1 1H5a1 1 0 0 0 1 1h9.5a.5.5 0 0 1 0 1H6a2 2 0 0 1-2-2zM15 4a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1v11h10V4zM7.041 8h.973c.045-.773.192-1.485.42-2.059A3.002 3.002 0 0 0 7.04 8zM6 8.5a4 4 0 1 1 8 0a4 4 0 0 1-8 0zm6.959-.5a3.002 3.002 0 0 0-1.392-2.059c.227.574.374 1.286.419 2.059h.973zm-.973 1c-.045.773-.192 1.486-.42 2.059A3.002 3.002 0 0 0 12.96 9h-.973zm-1.002-1c-.046-.707-.189-1.324-.383-1.778c-.12-.28-.25-.474-.368-.591c-.117-.115-.195-.131-.233-.131c-.038 0-.116.016-.233.13c-.118.118-.248.312-.368.592c-.194.454-.337 1.07-.383 1.778h1.968zM9.016 9c.046.707.189 1.324.383 1.778c.12.28.25.474.368.591c.117.115.195.131.233.131c.038 0 .116-.016.233-.13c.118-.118.248-.313.368-.592c.194-.454.336-1.07.383-1.778H9.016zM8.014 9h-.973c.147.87.668 1.614 1.392 2.059c-.227-.573-.374-1.286-.419-2.059z" fill = "currentColor" > < / path > < / g > < / svg >
2023-11-11 18:48:29 +08:00
< div class = "ellipsis" >
2023-12-26 10:59:02 +08:00
< span > 读书< / span >
< / div >
< / a >
< / li > < li class = "" >
< a href = "/categories/%E8%B4%A2%E7%BB%8F/" >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 24 24" > < g fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" > < circle cx = "12" cy = "12" r = "9" > < / circle > < path d = "M14.8 9A2 2 0 0 0 13 8h-2a2 2 0 0 0 0 4h2a2 2 0 0 1 0 4h-2a2 2 0 0 1-1.8-1" > < / path > < path d = "M12 6v2m0 8v2" > < / path > < / g > < / svg >
< div class = "ellipsis" >
< span > 财经< / span >
2023-11-11 18:48:29 +08:00
< / div >
< / a >
2023-11-10 13:44:10 +08:00
< / li > < / ul >
2023-12-25 16:39:03 +08:00
< / nav >
2023-10-24 09:50:42 +08:00
2023-12-28 11:27:53 +08:00
< script src = "/js/da8f6845.js" > < / script >
2023-10-24 09:50:42 +08:00
2023-12-25 16:39:03 +08:00
< / div >
< div class = "bottom" >
< cosy-tooltip id = "button-preference" placement = "right" >
< span slot = "content" >
< span > 偏好< / span >
< cosy-short-key > ⌘< / cosy-short-key >
< cosy-short-key > p< / cosy-short-key >
< / span >
< cosy-icon bordered id = "button-about-cosy-theme" >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 16 16" >
< g fill = "none" >
< path d = "M8 6a2 2 0 1 0 0 4a2 2 0 0 0 0-4zM7 8a1 1 0 1 1 2 0a1 1 0 0 1-2 0zm3.618-3.602a.708.708 0 0 1-.824-.567l-.26-1.416a.354.354 0 0 0-.275-.282a6.072 6.072 0 0 0-2.519 0a.354.354 0 0 0-.275.282l-.259 1.416a.71.71 0 0 1-.936.538l-1.359-.484a.355.355 0 0 0-.382.095c-.569.627-1 1.367-1.262 2.173a.352.352 0 0 0 .108.378l1.102.931a.704.704 0 0 1 0 1.076l-1.102.931a.352.352 0 0 0-.108.378A5.986 5.986 0 0 0 3.53 12.02a.355.355 0 0 0 .382.095l1.36-.484a.708.708 0 0 1 .936.538l.258 1.416c.026.14.135.252.275.281a6.075 6.075 0 0 0 2.52 0a.353.353 0 0 0 .274-.281l.26-1.416a.71.71 0 0 1 .936-.538l1.359.484c.135.048.286.01.382-.095c.569-.627 1-1.367 1.262-2.173a.352.352 0 0 0-.108-.378l-1.102-.931a.703.703 0 0 1 0-1.076l1.102-.931a.352.352 0 0 0 .108-.378A5.985 5.985 0 0 0 12.47 3.98a.355.355 0 0 0-.382-.095l-1.36.484a.71.71 0 0 1-.111.03zm-6.62.58l.937.333a1.71 1.71 0 0 0 2.255-1.3l.177-.97a5.105 5.105 0 0 1 1.265 0l.178.97a1.708 1.708 0 0 0 2.255 1.3L12 4.977c.255.334.467.698.63 1.084l-.754.637a1.704 1.704 0 0 0 0 2.604l.755.637a4.99 4.99 0 0 1-.63 1.084l-.937-.334a1.71 1.71 0 0 0-2.255 1.3l-.178.97a5.099 5.099 0 0 1-1.265 0l-.177-.97a1.708 1.708 0 0 0-2.255-1.3L4 11.023a4.987 4.987 0 0 1-.63-1.084l.754-.638a1.704 1.704 0 0 0 0-2.603l-.755-.637c.164-.386.376-.75.63-1.084z" fill = "currentColor" > < / path >
< / g >
< / svg >
< / cosy-icon >
< / cosy-tooltip >
2023-10-24 09:50:42 +08:00
< / div >
< / aside >
< main >
2023-12-26 10:56:25 +08:00
< link rel = "stylesheet" href = "/css/9bb9a539.css" >
2023-10-24 09:50:42 +08:00
< div class = "post-container" >
2023-12-25 16:39:03 +08:00
< header >
< div class = "left" >
2023-10-24 09:50:42 +08:00
2023-12-25 16:39:03 +08:00
< link rel = "stylesheet" href = "/css/7d333f9e.css" >
2023-10-24 09:50:42 +08:00
< nav class = "breadcrumb" >
2023-12-25 16:39:03 +08:00
< section >
< cosy-tooltip placement = "bottom-left" >
< span slot = "content" > < span > 首页< / span >
< cosy-short-key > ⌘< / cosy-short-key >
< cosy-short-key > H< / cosy-short-key >
< / span >
< cosy-icon href = "/" >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 20 20" >
< g fill = "none" >
< path d = "M8.998 2.388a1.5 1.5 0 0 1 2.005 0l5.5 4.942A1.5 1.5 0 0 1 17 8.445V15.5a1.5 1.5 0 0 1-1.5 1.5H13a1.5 1.5 0 0 1-1.5-1.5V12a.5.5 0 0 0-.5-.5H9a.5.5 0 0 0-.5.5v3.5A1.5 1.5 0 0 1 7 17H4.5A1.5 1.5 0 0 1 3 15.5V8.445c0-.425.18-.83.498-1.115l5.5-4.942zm1.336.744a.5.5 0 0 0-.668 0l-5.5 4.942A.5.5 0 0 0 4 8.445V15.5a.5.5 0 0 0 .5.5H7a.5.5 0 0 0 .5-.5V12A1.5 1.5 0 0 1 9 10.5h2a1.5 1.5 0 0 1 1.5 1.5v3.5a.5.5 0 0 0 .5.5h2.5a.5.5 0 0 0 .5-.5V8.445a.5.5 0 0 0-.166-.371l-5.5-4.942z" fill = "currentColor" > < / path >
< / g >
< / svg >
< / cosy-icon >
< / cosy-tooltip >
< svg class = "arrow" xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 20 20" >
2023-10-24 09:50:42 +08:00
< g fill = "none" >
< path d = "M7.733 4.207a.75.75 0 0 1 1.06.026l5.001 5.25a.75.75 0 0 1 0 1.035l-5 5.25a.75.75 0 1 1-1.087-1.034L12.216 10l-4.51-4.734a.75.75 0 0 1 .027-1.06z" fill = "currentColor" > < / path >
< / g >
< / svg >
2023-12-26 10:59:02 +08:00
< a class = "ellipsis" href = "/categories/CS/" >
CS
2023-12-25 16:39:03 +08:00
< / a >
< svg class = "arrow" xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 20 20" >
2023-10-24 09:50:42 +08:00
< g fill = "none" >
< path d = "M7.733 4.207a.75.75 0 0 1 1.06.026l5.001 5.25a.75.75 0 0 1 0 1.035l-5 5.25a.75.75 0 1 1-1.087-1.034L12.216 10l-4.51-4.734a.75.75 0 0 1 .027-1.06z" fill = "currentColor" > < / path >
< / g >
< / svg >
2023-12-25 16:39:03 +08:00
< span class = "ellipsis" >
verdaccio 搭建 npm私库
< / span >
< / section >
2023-10-24 09:50:42 +08:00
< / nav >
2023-10-20 10:28:01 +08:00
< script src = "/js/31d6cfe0.js" > < / script >
2023-10-24 09:50:42 +08:00
2023-12-25 16:39:03 +08:00
< / div >
< div class = "right" >
< cosy-tooltip id = "toc-show-button" placement = "left" >
< span slot = "content" >
< span > 显示 / 隐藏 文章目录< / span >
< cosy-short-key > ]< / cosy-short-key >
< / span >
< cosy-icon >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 20 20" >
< g fill = "none" >
< path d = "M4 4c-1.104-.019-2 .896-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2H4zM3 6a1 1 0 0 1 1-1h2.995v10H4a1 1 0 0 1-1-1V6zm4.995 9V5h8.004a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H7.995z" fill = "currentColor" > < / path >
< / g >
< / svg >
< / cosy-icon >
< / cosy-tooltip >
< / div >
< / header >
< div class = "content" >
< main class = "cosy-scrollbar" >
2023-10-24 09:50:42 +08:00
< div class = "article-container" >
<!-- 渲染文章内容 -->
2023-11-08 13:45:34 +08:00
< article >
2023-12-25 16:39:03 +08:00
<!-- 文章标题 -->
< h1 class = "post-title" > verdaccio 搭建 npm私库< / h1 >
< div class = "last-updated" >
2024-03-24 21:22:17 +08:00
上次更新: 2024-03-15 23:14:48
2023-12-25 16:39:03 +08:00
< / div >
<!-- 文章 -->
2023-11-08 13:45:34 +08:00
< h1 id = "使用-docker-搭建-verdaccio" > < a href = "#使用-docker-搭建-verdaccio" class = "headerlink" title = "使用 docker 搭建 verdaccio" > < / a > 使用 docker 搭建 verdaccio< / h1 > < p > 创建 & 配置< code > config.yaml< / code > 文件< / p >
2023-10-20 10:28:01 +08:00
< pre class = "line-numbers language-yaml" data-language = "yaml" > < code class = "language-yaml" > < span class = "token comment" > # Read about the best practices< / span >
< span class = "token comment" > # https://verdaccio.org/docs/best< / span >
< span class = "token comment" > # path to a directory with all packages< / span >
< span class = "token key atrule" > storage< / span > < span class = "token punctuation" > :< / span > /verdaccio/storage/data
< span class = "token comment" > # path to a directory with plugins to include< / span >
< span class = "token key atrule" > plugins< / span > < span class = "token punctuation" > :< / span > /verdaccio/plugins
< span class = "token comment" > # 包体积上限, 默认10mb< / span >
< span class = "token key atrule" > max_body_size< / span > < span class = "token punctuation" > :< / span > 1024mb
< span class = "token key atrule" > web< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > enable< / span > < span class = "token punctuation" > :< / span > < span class = "token boolean important" > true< / span >
< span class = "token key atrule" > title< / span > < span class = "token punctuation" > :< / span > Mozzie< span class = "token punctuation" > -< / span > NPM
< span class = "token comment" > # gravatar: false< / span >
< span class = "token comment" > # login: true< / span >
< span class = "token key atrule" > pkgManagers< / span > < span class = "token punctuation" > :< / span >
< span class = "token punctuation" > -< / span > npm
< span class = "token punctuation" > -< / span > yarn
< span class = "token punctuation" > -< / span > pnpm
< span class = "token key atrule" > html_cache< / span > < span class = "token punctuation" > :< / span > < span class = "token boolean important" > true< / span >
< span class = "token key atrule" > showFooter< / span > < span class = "token punctuation" > :< / span > < span class = "token boolean important" > false< / span >
< span class = "token key atrule" > auth< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > htpasswd< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > file< / span > < span class = "token punctuation" > :< / span > /verdaccio/storage/htpasswd
< span class = "token comment" > # 关闭注册, 手动添加用户, 默认Bcrypt算法, 随便找个网页生成个密码, 使用账号:密码添加到 htpasswd 文件中,例如 test:$2a$10$0xPGVnpcdxcfmFxtWyWDx./TRtm/W/gSzib/jck3w.sF9x.Ur8t8W< / span >
< span class = "token key atrule" > max_users< / span > < span class = "token punctuation" > :< / span > < span class = "token number" > -1< / span >
< span class = "token key atrule" > i18n< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > web< / span > < span class = "token punctuation" > :< / span > zh< span class = "token punctuation" > -< / span > CN
< span class = "token comment" > # notify: # 配置 Webhook 推送到钉钉,记得修改 access_token 和 atMobiles< / span >
< span class = "token comment" > # method: POST< / span >
< span class = "token comment" > # headers: [{ "Content-Type": "application/json" } ]< / span >
< span class = "token comment" > # endpoint: https://oapi.dingtalk.com/robot/send?access_token=xxxx< / span >
< span class = "token comment" > # content: '{ "msgtype":"text", "at": { "atMobiles": ["13000000000"] } , "text":{ "content":"NPM 发布新包:\n > 包名称:{ { name} } \n > 版本号:{ { #each versions} } { { version} } { { /each} } \n > 发布者:{ { publisher.name} } "} } '< / span >
< span class = "token key atrule" > uplinks< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > npmjs< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > url< / span > < span class = "token punctuation" > :< / span > https< span class = "token punctuation" > :< / span > //registry.npmjs.org/
< span class = "token key atrule" > yarn< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > url< / span > < span class = "token punctuation" > :< / span > https< span class = "token punctuation" > :< / span > //registry.yarnpkg.com/
< span class = "token key atrule" > timeout< / span > < span class = "token punctuation" > :< / span > 10s
< span class = "token key atrule" > taobao< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > url< / span > < span class = "token punctuation" > :< / span > https< span class = "token punctuation" > :< / span > //registry.npmmirror.com/
< span class = "token key atrule" > timeout< / span > < span class = "token punctuation" > :< / span > 10s
< span class = "token key atrule" > packages< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > "@*/*"< / span > < span class = "token punctuation" > :< / span >
< span class = "token comment" > # 可访问权限, web界面看不见, 不登陆, 也无法 install 包< / span >
< span class = "token key atrule" > access< / span > < span class = "token punctuation" > :< / span > $authenticated < span class = "token comment" > # $all< / span >
< span class = "token comment" > # 发布权限, $authenticated 表示只有通过验证的人< / span >
< span class = "token key atrule" > publish< / span > < span class = "token punctuation" > :< / span > $authenticated
< span class = "token comment" > # 可取消发布权限< / span >
< span class = "token key atrule" > unpublish< / span > < span class = "token punctuation" > :< / span > $authenticated
< span class = "token comment" > # 包不存在时的代理< / span >
< span class = "token key atrule" > proxy< / span > < span class = "token punctuation" > :< / span > npmjs yarn taobao
< span class = "token key atrule" > "**"< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > access< / span > < span class = "token punctuation" > :< / span > $authenticated < span class = "token comment" > # $all< / span >
< span class = "token key atrule" > publish< / span > < span class = "token punctuation" > :< / span > $authenticated
< span class = "token key atrule" > unpublish< / span > < span class = "token punctuation" > :< / span > $authenticated
< span class = "token key atrule" > proxy< / span > < span class = "token punctuation" > :< / span > npmjs yarn taobao
< span class = "token key atrule" > middlewares< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > audit< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > enabled< / span > < span class = "token punctuation" > :< / span > < span class = "token boolean important" > true< / span >
< span class = "token key atrule" > listen< / span > < span class = "token punctuation" > :< / span > 0.0.0.0< span class = "token punctuation" > :< / span > < span class = "token number" > 4873< / span >
< span class = "token key atrule" > log< / span > < span class = "token punctuation" > :< / span > < span class = "token punctuation" > { < / span > < span class = "token key atrule" > type< / span > < span class = "token punctuation" > :< / span > stdout< span class = "token punctuation" > ,< / span > < span class = "token key atrule" > format< / span > < span class = "token punctuation" > :< / span > pretty< span class = "token punctuation" > ,< / span > < span class = "token key atrule" > level< / span > < span class = "token punctuation" > :< / span > http < span class = "token punctuation" > } < / span > < span aria-hidden = "true" class = "line-numbers-rows" > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < / span > < / code > < / pre >
< p > 创建容器,环境变量,< code > VERDACCIO_PUBLIC_URL< / code > 是静态资源的前缀地址, 由于nginx挂了< code > ssl< / code > ,如果使用< code > http< / code > 可以不添加< / p >
< pre class = "line-numbers language-bash" data-language = "bash" > < code class = "language-bash" > < span class = "token function" > docker< / span > run < span class = "token punctuation" > \< / span >
< span class = "token parameter variable" > -p< / span > < span class = "token number" > 4873< / span > :4873 < span class = "token punctuation" > \< / span >
< span class = "token parameter variable" > --restart< / span > < span class = "token operator" > =< / span > always < span class = "token punctuation" > \< / span >
< span class = "token parameter variable" > --network< / span > mozzie.cn-net < span class = "token punctuation" > \< / span >
--network-alias verdaccio < span class = "token punctuation" > \< / span >
< span class = "token parameter variable" > --env< / span > < span class = "token assign-left variable" > VERDACCIO_PORT< / span > < span class = "token operator" > =< / span > < span class = "token number" > 4873< / span > < span class = "token punctuation" > \< / span >
< span class = "token parameter variable" > --env< / span > < span class = "token assign-left variable" > VERDACCIO_PUBLIC_URL< / span > < span class = "token operator" > =< / span > https://npm.mozzie.cn < span class = "token punctuation" > \< / span >
< span class = "token parameter variable" > --ip< / span > < span class = "token number" > 172.21< / span > .0.196 < span class = "token punctuation" > \< / span >
< span class = "token parameter variable" > --name< / span > verdaccio < span class = "token punctuation" > \< / span >
< span class = "token parameter variable" > -v< / span > /www/wwwroot/nginx/html/verdaccio/storage:/verdaccio/storage < span class = "token punctuation" > \< / span >
< span class = "token parameter variable" > -v< / span > /www/wwwroot/nginx/html/verdaccio/config:/verdaccio/conf < span class = "token punctuation" > \< / span >
< span class = "token parameter variable" > -v< / span > /www/wwwroot/nginx/html/verdaccio/plugins:/verdaccio/plugins < span class = "token punctuation" > \< / span >
< span class = "token parameter variable" > -d< / span > verdaccio/verdaccio< span aria-hidden = "true" class = "line-numbers-rows" > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < / span > < / code > < / pre >
< p > 配置nginx的反向代理conf, 注意所在的docker网络, 使用< code > container_name< / code > < / p >
< pre class = "line-numbers language-conf" data-language = "conf" > < code class = "language-conf" > server {
# listen 80;
listen 443 ssl;
server_name npm.mozzie.cn;
ssl_certificate / etc/ nginx/ ssl/ npm.mozzie.cn_bundle.pem;
ssl_certificate_key / etc/ nginx/ ssl/ npm.mozzie.cn.key;
gzip on;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http:/ / verdaccio:4873/ ;
proxy_redirect off;
}
} < span aria-hidden = "true" class = "line-numbers-rows" > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < / span > < / code > < / pre >
< p > 运行添加用户,报错,因为 < code > htpasswd< / code > 默认创建在宿主机,也就是上面挂载的< code > /www/wwwroot/nginx/html/verdaccio/storage< / code > 目录中< / p >
< pre class = "line-numbers language-bash" data-language = "bash" > < code class = "language-bash" > < span class = "token function" > npm< / span > adduser < span class = "token parameter variable" > --registry< / span > https://npm.mozzie.cn/< span aria-hidden = "true" class = "line-numbers-rows" > < span > < / span > < / span > < / code > < / pre >
< p > 配置< code > htpasswd< / code > 、< code > storage< / code > 文件夹权限< / p >
< pre class = "line-numbers language-bash" data-language = "bash" > < code class = "language-bash" > < span class = "token comment" > # 宿主机中执行< / span >
< span class = "token builtin class-name" > cd< / span > /www/wwwroot/nginx/html/verdaccio/storage
< span class = "token function" > touch< / span > htpasswd
< span class = "token function" > sudo< / span > < span class = "token function" > chown< / span > < span class = "token number" > 10001< / span > :65533 htpasswd
< span class = "token function" > sudo< / span > < span class = "token function" > chown< / span > < span class = "token parameter variable" > -R< / span > < span class = "token number" > 10001< / span > :65533 /www/wwwroot/nginx/html/verdaccio/storage< span aria-hidden = "true" class = "line-numbers-rows" > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < / span > < / code > < / pre >
< h1 id = "verdaccio-用户管理" > < a href = "#verdaccio-用户管理" class = "headerlink" title = "verdaccio 用户管理" > < / a > verdaccio 用户管理< / h1 > < p > 由于在 < code > config.yml< / code > 中关闭了可访问权限< / p >
< pre class = "line-numbers language-yaml" data-language = "yaml" > < code class = "language-yaml" > < span class = "token key atrule" > auth< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > htpasswd< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > file< / span > < span class = "token punctuation" > :< / span > /verdaccio/storage/htpasswd
< span class = "token comment" > # 关闭注册, 手动添加用户, 默认Bcrypt算法, < / span >
< span class = "token key atrule" > max_users< / span > < span class = "token punctuation" > :< / span > < span class = "token number" > -1< / span >
< span class = "token key atrule" > packages< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > "@*/*"< / span > < span class = "token punctuation" > :< / span >
< span class = "token comment" > # 可访问权限, web界面看不见, 不登陆, 也无法 install 包< / span >
< span class = "token key atrule" > access< / span > < span class = "token punctuation" > :< / span > $authenticated < span class = "token comment" > # $all< / span >
< span class = "token comment" > # 发布权限, $authenticated 表示只有通过验证的人< / span >
< span class = "token key atrule" > publish< / span > < span class = "token punctuation" > :< / span > $authenticated
< span class = "token comment" > # 可取消发布权限< / span >
< span class = "token key atrule" > unpublish< / span > < span class = "token punctuation" > :< / span > $authenticated
< span class = "token key atrule" > "**"< / span > < span class = "token punctuation" > :< / span >
< span class = "token key atrule" > access< / span > < span class = "token punctuation" > :< / span > $authenticated
< span class = "token key atrule" > publish< / span > < span class = "token punctuation" > :< / span > $authenticated
< span class = "token key atrule" > unpublish< / span > < span class = "token punctuation" > :< / span > $authenticated< span aria-hidden = "true" class = "line-numbers-rows" > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < / span > < / code > < / pre >
< p > 默认的 < code > addUser< / code > 策略是 < code > Bcrypt< / code > 生成密码,随便找个网页生成个密码,使用< code > 账号:密码< / code > 添加到 < code > htpasswd< / code > 文件中,例如 < / p >
< pre class = "line-numbers language-bash" data-language = "bash" > < code class = "language-bash" > test:< span class = "token variable" > $2a< / span > < span class = "token variable" > $10< / span > < span class = "token variable" > $0xPGVnpcdxcfmFxtWyWDx< / span > ./TRtm/W/gSzib/jck3w.sF9x.Ur8t8W< span aria-hidden = "true" class = "line-numbers-rows" > < span > < / span > < / span > < / code > < / pre >
< p > 因此在实际开发中,管理员手动给用户创建好账号,然后根据用户的包管理工具,进行登录,例如以 < code > npm< / code > 为例< / p >
< pre class = "line-numbers language-bash" data-language = "bash" > < code class = "language-bash" > < span class = "token function" > npm< / span > adduser < span class = "token parameter variable" > --registry< / span > https://npm.mozzie.cn/
< span class = "token comment" > # 输入 Username: mozzie | Password: xxx | Email: (this IS public) himozzie@foxmail.com< / span >
< span class = "token comment" > # 提示登陆成功 Logged in as mozzie on https://npm.mozzie.cn/.< / span > < span aria-hidden = "true" class = "line-numbers-rows" > < span > < / span > < span > < / span > < span > < / span > < / span > < / code > < / pre >
< p > 在系统的 < code > cat ~/.npmrc< / code > 中会增加一行,就可以正常的进行以来的安装了< / p >
< pre class = "line-numbers language-bash" data-language = "bash" > < code class = "language-bash" > //npm.mozzie.cn/:_authToken< span class = "token operator" > =< / span > < span class = "token string" > "Do/wrh5QzsnYaNU4x3ZlVA=="< / span > < span aria-hidden = "true" class = "line-numbers-rows" > < span > < / span > < / span > < / code > < / pre >
< h1 id = "项目-npmrc-Scope区分" > < a href = "#项目-npmrc-Scope区分" class = "headerlink" title = "项目 .npmrc Scope区分" > < / a > 项目 .npmrc Scope区分< / h1 > < p > 需要指定 < code > .npmrc< / code > 来区别 < code > Scope< / code > 的安装地址,例如一个包名为 < code > @mozzie/hook< / code > ,对应的私库为 < code > https://npm.mozzie.cn/< / code > < / p >
< pre class = "line-numbers language-bash" data-language = "bash" > < code class = "language-bash" > < span class = "token assign-left variable" > registry< / span > < span class = "token operator" > =< / span > http://registry.npm.taobao.org/
@mozzie:registry< span class = "token operator" > =< / span > https://npm.mozzie.cn
< span class = "token comment" > # npm拉包的校验< / span >
2023-11-08 13:45:34 +08:00
//https://npm.mozzie.cn/:_authToken< span class = "token operator" > =< / span > xxxxxxxxxxxxx< span aria-hidden = "true" class = "line-numbers-rows" > < span > < / span > < span > < / span > < span > < / span > < span > < / span > < / span > < / code > < / pre >
2023-12-25 16:39:03 +08:00
< div class = "post-tags" >
<!-- 文章tags -->
< / div >
< p class = "motto" > 重拾纯粹的写作< / p >
2023-11-08 13:45:34 +08:00
< / article >
2023-10-24 09:50:42 +08:00
<!-- 评论 -->
< div id = "vcomments" > < / div >
< / div >
< / main >
2023-12-25 16:39:03 +08:00
<!-- toc -->
< cosy-drag-box id = "toc-drag-box" trigger = "left" min-width = "220" uid = "toc-box" >
< div class = "meta-container" >
< div class = "toc-wrapper cosy-scrollbar" >
2023-12-26 10:56:25 +08:00
< p class = "catalog" >
< svg xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 24 24" >
< g fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" >
< path d = "M4 6h16" > < / path >
< path d = "M4 12h16" > < / path >
< path d = "M4 18h12" > < / path >
< / g >
< / svg >
< span > 目录< / span >
< / p >
2023-12-25 16:39:03 +08:00
<!-- 文章toc -->
< ol class = "toc" > < li class = "toc-item toc-level-1" > < a class = "toc-link" href = "#%E4%BD%BF%E7%94%A8-docker-%E6%90%AD%E5%BB%BA-verdaccio" > < span class = "toc-number" > 1.< / span > < span class = "toc-text" > 使用 docker 搭建 verdaccio< / span > < / a > < / li > < li class = "toc-item toc-level-1" > < a class = "toc-link" href = "#verdaccio-%E7%94%A8%E6%88%B7%E7%AE%A1%E7%90%86" > < span class = "toc-number" > 2.< / span > < span class = "toc-text" > verdaccio 用户管理< / span > < / a > < / li > < li class = "toc-item toc-level-1" > < a class = "toc-link" href = "#%E9%A1%B9%E7%9B%AE-npmrc-Scope%E5%8C%BA%E5%88%86" > < span class = "toc-number" > 3.< / span > < span class = "toc-text" > 项目 .npmrc Scope区分< / span > < / a > < / li > < / ol >
< / div >
< / div >
< / cosy-drag-box >
2023-10-24 09:50:42 +08:00
< / div >
2023-12-25 16:39:03 +08:00
2023-10-24 09:50:42 +08:00
< / div >
< script >
2023-11-08 10:11:56 +08:00
window.page = {
use: ''
}
2023-10-24 09:50:42 +08:00
window.katex = {
2023-11-08 10:11:56 +08:00
enable: "",
2023-10-24 09:50:42 +08:00
jsCdn: "//cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.js",
cssCdn: "//cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.css"
}
window.mermaid = {
2023-11-08 10:11:56 +08:00
enable: "",
2023-11-15 10:21:41 +08:00
theme: "",
2023-10-24 09:50:42 +08:00
cdn: "//cdn.jsdelivr.net/npm/mermaid@10.4.0/dist/mermaid.min.js",
}
window.valine = {
2023-11-08 10:11:56 +08:00
enable: "",
2023-10-24 09:50:42 +08:00
appId: 'TisMit6uhflounFqAN3ZGjgq-MdYXbMMI',
appKey: 'CdjirjYdz07U5i62ElsJvXUh',
avatar: 'monsterid',
cdn: '//unpkg.com/valine@latest/dist/Valine.min.js',
serverURLs: '//tismit6u.api.lncldglobal.com'
};
< / script >
2023-12-28 11:27:53 +08:00
< script src = "/js/5bf38c1b.js" > < / script >
2023-10-24 09:50:42 +08:00
< / main >
< / body >
2023-12-25 16:39:03 +08:00
2023-10-24 09:50:42 +08:00
< script >
2023-12-25 16:39:03 +08:00
window.theme = {
color: 'hsl(238,50%,56%)'
2023-10-24 09:50:42 +08:00
}
< / script >
2023-12-25 16:39:03 +08:00
2023-12-28 11:27:53 +08:00
< script src = "/js/82a967e8.js" > < / script >
2023-10-24 09:50:42 +08:00
2023-10-20 10:28:01 +08:00
< / html >