목차
노드 및 노드 라이브러리 가져오기
nodePress.js
本地运行
结论
웹 프론트엔드 JS 튜토리얼 콘텐츠 관리 시스템 만들기: nodePress

콘텐츠 관리 시스템 만들기: nodePress

Sep 03, 2023 pm 01:53 PM

<p>Go를 사용하여 플랫 파일 시스템 콘텐츠 관리 시스템(CMS)을 성공적으로 만들었습니다. 다음 단계는 동일한 아이디어를 가지고 Node.js를 사용하여 웹 서버를 만드는 것입니다. 라이브러리를 로드하고, 서버를 생성하고, 서버를 실행하는 방법을 보여드리겠습니다. </p> <p>이 CMS는 첫 번째 튜토리얼 "CMS 구축: 구조 및 스타일"에서 소개된 사이트 데이터 구조를 사용합니다. 따라서 이 기본 구조를 다운로드하여 새 디렉토리에 설치하십시오. </p> <h2 id="노드-및-노드-라이브러리-가져오기">노드 및 노드 라이브러리 가져오기</h2> <p>Mac에 Node.js를 설치하는 가장 쉬운 방법은 Homebrew를 사용하는 것입니다. Homebrew가 아직 설치되어 있지 않은 경우 Homebrew Revealed: The Ultimate Package Manager for OS X 튜토리얼에서 설치 방법을 보여줍니다. </p> <p>Homebrew를 사용하여 Node.js를 설치하려면 터미널에 다음 명령을 입력하세요. </p> 으아악 <p>완료되면 Node 및 npm 명령이 Mac에 완전히 설치됩니다. 다른 모든 플랫폼의 경우 Node.js 웹사이트의 지침을 따르세요. </p> <p>참고: 현재 많은 패키지 관리자가 Node.js 버전 0.10을 설치하고 있습니다. 이 튜토리얼에서는 버전 5.3 이상이 있다고 가정합니다. 다음을 입력하여 버전을 확인할 수 있습니다. </p> 으아악 <p><code class="inline">node</code> 命令运行 JavaScript 解释器。 <code class="inline">npm</code> 명령은 Node.js의 패키지 관리자이며 새 라이브러리를 설치하고, 새 프로젝트를 만들고, 프로젝트 스크립트를 실행하는 데 사용됩니다. Envato Tuts+에는 Node.js 및 NPM에 대한 훌륭한 튜토리얼과 강좌가 많이 있습니다. </p> <p>웹 서버의 라이브러리를 설치하려면 Terminal.app 또는 iTerm.app 프로그램에서 다음 명령을 실행해야 합니다. </p> 으아악 <p>Express는 웹 애플리케이션 개발 플랫폼입니다. Go의 goWeb 라이브러리와 유사합니다. 핸들바는 페이지 생성을 위한 템플릿 엔진입니다. Moment는 날짜 작업을 위한 라이브러리입니다. Marked는 JavaScript의 HTML 변환기로 훌륭한 Markdown을 제공합니다. Jade는 HTML을 쉽게 생성할 수 있게 해주는 HTML 속기 언어입니다. Morgan은 Apache 표준 로그 파일을 생성하는 Express용 미들웨어 라이브러리입니다. </p> <p>라이브러리를 설치하는 또 다른 방법은 이 튜토리얼의 소스 파일을 다운로드하는 것입니다. 다운로드하고 압축을 푼 후 기본 디렉터리에 다음을 입력하세요. </p> 으아악 <p>이렇게 하면 이 프로젝트를 만드는 데 필요한 모든 것이 설치됩니다. </p> <h2 id="nodePress-js">nodePress.js</h2> <p>이제 서버 생성을 시작할 수 있습니다. 프로젝트의 최상위 디렉터리에서 nodePress.js라는 파일을 만들고 원하는 편집기에서 열고 다음 코드를 추가하기 시작합니다. 파일에 넣은 코드를 설명하겠습니다. </p> 으아악 <p>서버 코드는 서버를 생성하는 데 사용된 모든 라이브러리를 초기화하는 것부터 시작됩니다. URL이 포함된 주석이 없는 라이브러리는 내부 Node.js 라이브러리입니다. </p> 으아악 <p>다음으로 모든 전역 변수와 라이브러리 구성을 설정했습니다. 전역 변수를 사용하는 것은 최고의 소프트웨어 설계 방식은 아니지만 빠른 개발에 효과가 있고 도움이 됩니다. </p> <p><code class="inline">parts</code> 변수는 웹페이지의 모든 부분을 포함하는 해시 배열입니다. 각 페이지는 이 변수의 내용을 참조합니다. 이는 서버 디렉터리 상단에 있는 server.json 파일의 내용으로 시작됩니다. </p> <p>그런 다음 server.json 파일의 정보를 사용하여 이 사이트의 <code class="inline">styles</code> 和 <code class="inline">layouts</code> 디렉터리에 대한 전체 경로를 만들었습니다. </p> <p>그런 다음 세 개의 변수를 빈 값으로 설정합니다. <code class="inline">siteCSS</code>、<code class="inline">siteScripts</code> 和 <code class="inline">mainPage</code>。这些全局变量将包含所有 CSS、JavaScript 和主索引页内容。这三个项目是任何 Web 服务器上请求最多的项目。因此,将它们保留在内存中可以节省时间。如果 server.json 文件中的 <code class="inline">Cache</code> 변수가 false이면 요청이 있을 때마다 항목을 다시 읽습니다. </p> 으아악 <p>이 코드 블록은 Markdown에서 HTML을 생성하도록 Marked 라이브러리를 구성하는 데 사용됩니다. 대부분의 경우 테이블과 smartList 지원을 켭니다. </p> 으아악 <p><code class="inline">parts</code> 变量进一步加载 <code class="inline">styles</code> 和 <code class="inline">layout</code> 目录中的部分。 <code class="inline">site</code> 目录内的 <code class="inline">parts</code> 目录中的每个文件也被加载到 <code class="inline">parts</code> 변수는 <code class="inline">styles</code> 및 <code class="inline">layout</code> 디렉터리의 섹션을 추가로 로드합니다. <code class="inline">site</code> 디렉터리 내 </p> 디렉터리의 각 파일도 <p> 전역 변수에 로드됩니다. 확장자가 없는 파일 이름은 파일 내용을 저장하는 데 사용되는 이름입니다. 이러한 이름은 Handlebars 매크로에서 확장됩니다. <code class="inline">save</code>、<code class="inline">date</code> 和 <code class="inline">cdate</code> 으아악 </p>다음 코드 조각은 웹 서버에서 사용하기 위해 정의한 Handlebars 도우미를 정의합니다. <p>. 저장 도우미를 사용하면 페이지 내에서 변수를 생성할 수 있습니다. 이 버전은 매개변수의 이름과 값이 "|"로 구분된 goPress 버전을 지원합니다. 두 개의 매개변수를 사용하여 저장을 지정할 수도 있습니다. 예: </p> 으아악 🎜이렇게 하면 동일한 결과가 나타납니다. 나는 두 번째 접근 방식을 선호하지만 Go의 Handlebars 라이브러리는 여러 매개변수를 허용하지 않습니다. 🎜 <p><code class="inline">date</code> 和 <code class="inline">cdate</code> 帮助程序格式化当前日期 (<code class="inline">date</code>) 或给定日期 (<code class="inline">cdate</code>)根据 <strong>moment.js</strong> 库格式化规则。 <code class="inline">cdate</code> 帮助程序期望渲染的日期是第一个参数并且具有 ISO 8601 格式。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Create and configure the server. // var nodePress = express(); // // Configure middleware. // nodePress.use(morgan('combined')) </pre><div class="contentsignin">로그인 후 복사</div></div> <p>现在,代码创建一个 Express 实例来配置实际的服务器引擎。 <code>nodePress.use()</code> 函数设置中间件软件。中间件是在每次调用服务器时提供服务的任何代码。在这里,我设置了 Morgan.js 库来创建正确的服务器日志输出。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Define the routes. // nodePress.get('/', function(request, response) { setBasicHeader(response); if((parts["Cache"] == true) && (mainPage != null)) { response.send(mainPage); } else { mainPage = page("main"); response.send(mainPage); } }); nodePress.get('/favicon.ico', function(request, response) { var options = { root: parts['Sitebase'] + 'images/', dotfiles: 'deny', headers: { 'x-timestamp': Date.now(), 'x-sent': true } }; response.set("Content-Type", "image/ico"); setBasicHeader(response); response.sendFile('favicon.ico', options, function(err) { if (err) { console.log(err); response.status(err.status).end(); } else { console.log('Favicon was sent:', 'favicon.ico'); } }); }); nodePress.get('/stylesheets.css', function(request, response) { response.set("Content-Type", "text/css"); setBasicHeader(response); response.type("css"); if((parts["Cache"] == true) && (siteCSS != null)) { response.send(siteCSS); } else { siteCSS = fs.readFileSync(parts['Sitebase'] + 'css/final/final.css'); response.send(siteCSS); } }); nodePress.get('/scripts.js', function(request, response) { response.set("Content-Type", "text/javascript"); setBasicHeader(response); if((parts["Cache"] == true) && (siteScripts != null)) { response.send(siteScripts); } else { siteScripts = fs.readFileSync(parts['Sitebase'] + 'js/final/final.js', 'utf8'); response.send(siteScripts); } }); nodePress.get('/images/:image', function(request, response) { var options = { root: parts['Sitebase'] + 'images/', dotfiles: 'deny', headers: { 'x-timestamp': Date.now(), 'x-sent': true } }; response.set("Content-Type", "image/" + path.extname(request.params.image).substr(1)); setBasicHeader(response); response.sendFile(request.params.image, options, function(err) { if (err) { console.log(err); response.status(err.status).end(); } else { console.log('Image was sent:', request.params.image); } }); }); nodePress.get('/posts/blogs/:blog', function(request, response) { setBasicHeader(response); response.send(post("blogs", request.params.blog, "index")); }); nodePress.get('/posts/blogs/:blog/:post', function(request, response) { setBasicHeader(response); response.send(post("blogs", request.params.blog, request.params.post)); }); nodePress.get('/posts/news/:news', function(request, response) { setBasicHeader(response); response.send(post("news", request.params.news, "index")); }); nodePress.get('/posts/news/:news/:post', function(request, response) { setBasicHeader(response); response.send(post("news", request.params.news, request.params.post)); }); nodePress.get('/:page', function(request, response) { setBasicHeader(response); response.send(page(request.params.page)); }); </pre><div class="contentsignin">로그인 후 복사</div></div> <p>这部分代码定义了实现 Web 服务器所需的所有路由。所有路由都运行 <code>setBasicHeader()</code> 函数来设置正确的标头值。所有针对页面类型的请求都会调用 <code>page()</code> 函数,而所有针对 post 类型页面的请求都会调用 <code>posts()</code> 函数。</p> <p><code class="inline">Content-Type</code> 的默认值为 HTML。因此,对于 CSS、JavaScript 和图像,<code class="inline">Content-Type</code> 显式设置为其适当的值。</p> <p>您还可以使用 <code>put</code>、<code>delete</code> 和 <code>post</code> REST 动词定义路由。这个简单的服务器仅使用 <code>get</code> 动词。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Start the server. // var addressItems = parts['ServerAddress'].split(':'); var server = nodePress.listen(addressItems[2], function() { var host = server.address().address; var port = server.address().port; console.log('nodePress is listening at http://%s:%s', host, port); }); </pre><div class="contentsignin">로그인 후 복사</div></div> <p>在定义所使用的不同函数之前要做的最后一件事是启动服务器。 server.json 文件包含 DNS 名称(此处为 <code>localhost</code>)和服务器的端口。解析后,服务器的 <code>listen()</code> 函数使用端口号来启动服务器。服务器端口打开后,脚本会记录服务器的地址和端口。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Function: setBasicHeader // // Description: This function will set the basic header information // needed. // // Inputs: // response The response object // function setBasicHeader(response) { response.append("Cache-Control", "max-age=2592000, cache"); response.append("Server", "nodePress - a CMS written in node from Custom Computer Tools: http://customct.com."); } </pre><div class="contentsignin">로그인 후 복사</div></div> <p>定义的第一个函数是 <code>setBasicHeader()</code> 函数。该函数设置响应头,告诉浏览器将页面缓存一个月。它还告诉浏览器该服务器是nodePress服务器。如果您需要任何其他标准标头值,您可以使用 <code>response.append()</code> 函数在此处添加它们。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Function: page // // Description: This function processes a page request // // Inputs: // page The requested page // function page(page) { // // Process the given page using the standard layout. // return (processPage(parts["layout"], parts['Sitebase'] + "pages/" + page)); } </pre><div class="contentsignin">로그인 후 복사</div></div> <p><code>page()</code> 函数将页面的布局模板以及页面在服务器上的位置发送到 <code>processPage()</code> 函数。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Function: post // // Description: This function processes a post request // // Inputs: // type The type of post. // cat The category of the post. // post The requested post // function post(type, cat, post) { // // Process the post given the type and the post name. // return (processPage(parts["layout"], parts['Sitebase'] + "posts/" + type + "/" + cat + "/" + post)); } </pre><div class="contentsignin">로그인 후 복사</div></div> <p><code>post()</code> 函数就像 <code>page()</code> 函数,不同之处在于帖子有更多项目来定义每个帖子。在这个系列的服务器中,一个post包含一个<code>type</code>、category,以及实际的<code>post</code>。类型为 <code>blogs</code> 或 <code>news</code>。类别是 <code>flatcms</code>。由于这些代表目录名称,因此您可以将它们设为您想要的任何名称。只需将命名与文件系统中的名称相匹配即可。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Function: processPage // // Description: This function processes a page for the CMS. // // Inputs: // layout The layout to use for the page. // page Path to the page to render. // function processPage(layout, page) { // // Get the pages contents and add to the layout. // var context = {}; context = MergeRecursive(context, parts); context['content'] = figurePage(page); context['PageName'] = path.basename(page, path.extname(page)); // // Load page data. // if(fileExists(page + ".json")) { // // Load the page's data file and add it to the data structure. // context = MergeRecursive(context, JSON.parse(fs.readFileSync(page + '.json', 'utf8'))); } // // Process Handlebars codes. // var template = Handlebars.compile(layout); var html = template(context); // // Process all shortcodes. // html = processShortCodes(html); // // Run through Handlebars again. // template = Handlebars.compile(html); html = template(context); // // Return results. // return (html); } </pre><div class="contentsignin">로그인 후 복사</div></div> <p><code>processPage()</code> 函数获取要呈现的页面内容的布局和路径。该函数首先创建 <code>parts</code> 全局变量的本地副本,并添加“contents”主题标签以及调用 <code>figurePage()</code> 函数的结果。然后,它将 <code>PageName</code> 哈希值设置为页面名称。</p> <p>然后,该函数使用 Handlebars 将页面内容编译到布局模板。之后, <code>processShortCodes()</code> 函数将展开页面上定义的所有短代码。然后,Handlebars 模板引擎再次检查代码。然后浏览器接收结果。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Function: processShortCodes // // Description: This function takes a string and // processes all of the shortcodes in // the string. // // Inputs: // content String to process // function processShortCodes(content) { // // Create the results variable. // var results = ""; // // Find the first match. // var scregFind = /\-\[([^\]]*)\]\-/i; var match = scregFind.exec(content); if (match != null) { results += content.substr(0,match.index); var scregNameArg = /(\w+)(.*)*/i; var parts = scregNameArg.exec(match[1]); if (parts != null) { // // Find the closing tag. // var scregClose = new RegExp("\\-\\[\\/" + parts[1] + "\\]\\-"); var left = content.substr(match.index + 4 + parts[1].length); var match2 = scregClose.exec(left); if (match2 != null) { // // Process the enclosed shortcode text. // var enclosed = processShortCodes(content.substr(match.index + 4 + parts[1].length, match2.index)); // // Figure out if there were any arguments. // var args = ""; if (parts.length == 2) { args = parts[2]; } // // Execute the shortcode. // results += shortcodes[parts[1]](args, enclosed); // // Process the rest of the code for shortcodes. // results += processShortCodes(left.substr(match2.index + 5 + parts[1].length)); } else { // // Invalid shortcode. Return full string. // results = content; } } else { // // Invalid shortcode. Return full string. // results = content; } } else { // // No shortcodes found. Return the string. // results = content; } return (results); } </pre><div class="contentsignin">로그인 후 복사</div></div> <p><code>processShortCodes()</code> 函数将网页内容作为字符串并搜索所有短代码。短代码是类似于 HTML 标签的代码块。一个例子是:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>-[box]- <p>This is inside a box</p> -[/box]- </pre><div class="contentsignin">로그인 후 복사</div></div> <p>此代码在 HTML 段落周围有一个 <code>box</code> 的简码。其中 HTML 使用 <code><</code> 和 </code>>></code>,短代码使用 <code>-[</code> 和 </code>>]-</code>。在名称后面,可以包含或不可以包含包含短代码参数的字符串。</p> <p><code>processShortCodes()</code> 函数查找短代码,获取其名称和参数,找到末尾以获取内容,处理短代码的内容,使用参数和内容执行短代码,将结果添加到完成中页面,并在页面的其余部分搜索下一个短代码。循环是通过递归调用函数来执行的。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Define the shortcodes function array. // var shortcodes = { 'box': function(args, inside) { return ("<div class='box'>" + inside + "</div>"); }, 'Column1': function(args, inside) { return ("<div class='col1'>" + inside + "</div>"); }, 'Column2': function(args, inside) { return ("<div class='col2'>" + inside + "</div>"); }, 'Column1of3': function(args, inside) { return ("<div class='col1of3'>" + inside + "</div>"); }, 'Column2of3': function(args, inside) { return ("<div class='col2of3'>" + inside + "</div>"); }, 'Column3of3': function(args, inside) { return ("<div class='col3of3'>" + inside + "</div>"); }, 'php': function(args, inside) { return ("<div class='showcode'><pre type='syntaxhighlighter' class='brush: php'>" + inside + "</pre><div class="contentsignin">로그인 후 복사</div></div></div>"); }, 'js': function(args, inside) { return ("<div class='showcode'><div class="code" style="position:relative; padding:0px; margin:0px;"><pre type='syntaxhighlighter' class='brush: javascript'>" + inside + "</pre><div class="contentsignin">로그인 후 복사</div></div></div>"); }, 'html': function(args, inside) { return ("<div class='showcode'><div class="code" style="position:relative; padding:0px; margin:0px;"><pre type='syntaxhighlighter' class='brush: html'>" + inside + "</pre><div class="contentsignin">로그인 후 복사</div></div></div>"); }, 'css': function(args, inside) { return ("<div class='showcode'><div class="code" style="position:relative; padding:0px; margin:0px;"><pre type='syntaxhighlighter' class='brush: css'>" + inside + "</pre><div class="contentsignin">로그인 후 복사</div></div></div>"); } }; </pre> <p>下一节定义 <code>shortcodes</code> json 结构,该结构定义与其函数关联的短代码的名称。所有短代码函数都接受两个参数:<code>args</code> 和 <code>inside</code>。 <code>args</code> 是名称和空格之后、标签结束之前的所有内容。 <code>inside</code> 是开始和结束短代码标记包含的所有内容。这些功能是基本功能,但您可以创建一个短代码来执行您能在 JavaScript 中想到的任何功能。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Function: figurePage // // Description: This function figures the page type // and loads the contents appropriately // returning the HTML contents for the page. // // Inputs: // page The page to load contents. // function figurePage(page) { var result = ""; if (fileExists(page + ".html")) { // // It's an HTML file. Read it in and send it on. // result = fs.readFileSync(page + ".html"); } else if (fileExists(page + ".amber")) { // // It's a jade file. Convert to HTML and send it on. I // am still using the amber extension for compatibility // to goPress. // var jadeFun = jade.compileFile(page + ".amber", {}); // Render the function var result = jadeFun({}); } else if (fileExists(page + ".md")) { // // It's a markdown file. Convert to HTML and send // it on. // result = marked(fs.readFileSync(page + ".md").toString()); // // This undo marked's URI encoding of quote marks. // result = result.replace(/\&quot\;/g,"\""); } return (result); } </pre><div class="contentsignin">로그인 후 복사</div></div> <p><code>figurePage()</code> 函数接收服务器上页面的完整路径。然后,此函数根据扩展名测试它是否为 HTML、Markdown 或 Jade 页面。我仍然在 Jade 中使用 .amber,因为那是我在 goPress 服务器上使用的库。所有 Markdown 和 Jade 内容都会先转换为 HTML,然后再传递给调用例程。由于 Markdown 处理器将所有引号翻译为 <code>"</code>,因此我在传回之前将它们翻译回来。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Function: fileExists // // Description: This function returns a boolean true if // the file exists. Otherwise, false. // // Inputs: // filePath Path to a file in a string. // function fileExists(filePath) { try { return fs.statSync(filePath).isFile(); } catch (err) { return false; } } </pre><div class="contentsignin">로그인 후 복사</div></div> <p><code>fileExists()</code> 函数是 <code>fs.exists()</code> 函数的替代品,该函数曾经是 Node.js 的 <code>fs</code> 库的一部分。它使用 <code>fs.statSync()</code> 函数来尝试获取文件的状态。如果发生错误,则会返回 <code>false</code>。否则,返回 <code>true</code>。</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>// // Function: MergeRecursive // // Description: Recursively merge properties of two objects // // Inputs: // obj1 The first object to merge // obj2 The second object to merge // function MergeRecursive(obj1, obj2) { for (var p in obj2) { try { // Property in destination object set; update its value. if (obj2[p].constructor == Object) { obj1[p] = MergeRecursive(obj1[p], obj2[p]); } else { obj1[p] = obj2[p]; } } catch (e) { // Property in destination object not set; create it and set its value. obj1[p] = obj2[p]; } } return obj1; } </pre><div class="contentsignin">로그인 후 복사</div></div> <p>最后一个函数是 <code>MergeRecursive()</code> 函数。它将第二个传递对象复制到第一个传递对象中。在添加特定于页面的部分之前,我利用它将主 <code>parts</code> 全局变量复制到本地副本中。</p> <h3 id="本地运行">本地运行</h3> <p>保存文件后,您可以使用以下命令运行服务器:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>node nodePress.js </pre><div class="contentsignin">로그인 후 복사</div></div> <p>或者,您可以使用 package.json 文件中的 <code class="inline">npm</code> 脚本。您可以像这样运行 npm 脚本:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>npm start </pre><div class="contentsignin">로그인 후 복사</div></div> <p>这将运行 package.json 文件内的 <code>start</code> 脚本。</p> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/164/169372039225694.jpg" class="lazy" alt="콘텐츠 관리 시스템 만들기: nodePress"></p> <p>将您的网络浏览器指向 <code>http://localhost:8080</code>,您将看到上面的页面。您可能已经注意到我在主页上添加了更多测试代码。对页面的所有更改都包含在本教程的下载中。它们大多只是一些小的调整,以更全面地测试功能并适应使用不同库的任何差异。最显着的区别是 Jade 库不使用 <code class="inline">$</code> 来命名变量,而 Amber 则使用。</p> <h2 id="结论">结论</h2> <p>现在,您在 Go 和 Node.js 中拥有完全相同的平面文件系统 CMS。这只是您可以使用此平台构建的内容的表面。尝试并尝试新事物。这是创建您自己的网络服务器的最佳部分。</p>

위 내용은 콘텐츠 관리 시스템 만들기: nodePress의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

내 자신의 JavaScript 라이브러리를 어떻게 작성하고 게시합니까? 내 자신의 JavaScript 라이브러리를 어떻게 작성하고 게시합니까? Mar 18, 2025 pm 03:12 PM

기사는 JavaScript 라이브러리 작성, 게시 및 유지 관리, 계획, 개발, 테스트, 문서 및 홍보 전략에 중점을 둡니다.

브라우저에서 성능을 위해 JavaScript 코드를 최적화하려면 어떻게해야합니까? 브라우저에서 성능을 위해 JavaScript 코드를 최적화하려면 어떻게해야합니까? Mar 18, 2025 pm 03:14 PM

이 기사는 브라우저에서 JavaScript 성능을 최적화하기위한 전략에 대해 설명하고 실행 시간을 줄이고 페이지로드 속도에 미치는 영향을 최소화하는 데 중점을 둡니다.

프론트 엔드 열 용지 영수증에 대한 차량 코드 인쇄를 만나면 어떻게해야합니까? 프론트 엔드 열 용지 영수증에 대한 차량 코드 인쇄를 만나면 어떻게해야합니까? Apr 04, 2025 pm 02:42 PM

프론트 엔드 개발시 프론트 엔드 열지대 티켓 인쇄를위한 자주 묻는 질문과 솔루션, 티켓 인쇄는 일반적인 요구 사항입니다. 그러나 많은 개발자들이 구현하고 있습니다 ...

브라우저 개발자 도구를 사용하여 JavaScript 코드를 효과적으로 디버그하려면 어떻게해야합니까? 브라우저 개발자 도구를 사용하여 JavaScript 코드를 효과적으로 디버그하려면 어떻게해야합니까? Mar 18, 2025 pm 03:16 PM

이 기사는 브라우저 개발자 도구를 사용하여 효과적인 JavaScript 디버깅, 중단 점 설정, 콘솔 사용 및 성능 분석에 중점을 둡니다.

누가 더 많은 파이썬이나 자바 스크립트를 지불합니까? 누가 더 많은 파이썬이나 자바 스크립트를 지불합니까? Apr 04, 2025 am 12:09 AM

기술 및 산업 요구에 따라 Python 및 JavaScript 개발자에 대한 절대 급여는 없습니다. 1. 파이썬은 데이터 과학 및 기계 학습에서 더 많은 비용을 지불 할 수 있습니다. 2. JavaScript는 프론트 엔드 및 풀 스택 개발에 큰 수요가 있으며 급여도 상당합니다. 3. 영향 요인에는 경험, 지리적 위치, 회사 규모 및 특정 기술이 포함됩니다.

소스 맵을 사용하여 조정 된 JavaScript 코드를 디버그하는 방법은 무엇입니까? 소스 맵을 사용하여 조정 된 JavaScript 코드를 디버그하는 방법은 무엇입니까? Mar 18, 2025 pm 03:17 PM

이 기사는 소스 맵을 사용하여 원래 코드에 다시 매핑하여 미니어링 된 JavaScript를 디버그하는 방법을 설명합니다. 소스 맵 활성화, 브레이크 포인트 설정 및 Chrome Devtools 및 Webpack과 같은 도구 사용에 대해 설명합니다.

Chart.js : Pie, Donut 및 Bubble Charts를 시작합니다 Chart.js : Pie, Donut 및 Bubble Charts를 시작합니다 Mar 15, 2025 am 09:19 AM

이 튜토리얼은 Chart.js를 사용하여 파이, 링 및 버블 차트를 만드는 방법을 설명합니다. 이전에는 차트 유형의 차트 유형을 배웠습니다. JS : 라인 차트 및 막대 차트 (자습서 2)와 레이더 차트 및 극지 지역 차트 (자습서 3)를 배웠습니다. 파이 및 링 차트를 만듭니다 파이 차트와 링 차트는 다른 부분으로 나뉘어 진 전체의 비율을 보여주는 데 이상적입니다. 예를 들어, 파이 차트는 사파리에서 남성 사자, 여성 사자 및 젊은 사자의 비율 또는 선거에서 다른 후보자가받는 투표율을 보여주는 데 사용될 수 있습니다. 파이 차트는 단일 매개 변수 또는 데이터 세트를 비교하는 데만 적합합니다. 파이 차트의 팬 각도는 데이터 포인트의 숫자 크기에 의존하기 때문에 원형 차트는 값이 0 인 엔티티를 그릴 수 없습니다. 이것은 비율이 0 인 모든 엔티티를 의미합니다

Console.log 출력 결과의 차이 : 두 통화가 다른 이유는 무엇입니까? Console.log 출력 결과의 차이 : 두 통화가 다른 이유는 무엇입니까? Apr 04, 2025 pm 05:12 PM

Console.log 출력의 차이의 근본 원인에 대한 심층적 인 논의. 이 기사에서는 Console.log 함수의 출력 결과의 차이점을 코드에서 분석하고 그에 따른 이유를 설명합니다. � ...

See all articles