zl程序教程

您现在的位置是:首页 >  后端

当前栏目

node.js入门笔记(七)——webpack与art-template、项目结构的初始化

2023-09-27 14:28:02 时间


    前面已经介绍了很多关于node.js的理论知识了,但是缺乏实战。实战还是比较重要的,因此希望能够像之前thinkPHP一样,将这些基础知识和项目实战的关键点记录下来,方便之后自己翻阅,也分享给大家,如果有不对的地方,欢迎在评论区批评指正。

1.webpack的引入

    对于webpack这个项目打包工具,相信大家应该不陌生。我这里也只是了解其优点和基本使用方法,如果想要研究的更加深入,可以去查看(webpack官网),或者可以去瞅瞅我之前看vue2的相关笔记:(Vue学习杂记(四)——webpack的基本使用),这里还是再简单总结一下webpack的基本使用方式:
(1)首先安装第三方依赖webpackwebpack-cli(生产环境安装即可);
(2)接下来安装copy-webpack-pluginhtml-webpack-plugin,前者是用来打包的时候复制特殊文件到指定位置,后者是用来打包时候处理html入口文件的。
(3)然后需要安装webpack-dev-server,这个是生产环境下用来进行热重载的webpack依赖,当代码更新时会自动重启服务,提高我们的开发效率。
(4)在根目录下创建一个webpack.config.js,这个是webpack的默认配置文件。
    下面展示一下文件结构和webpack.config.js文件配置信息:
在这里插入图片描述

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
	//指定当前使用的模式是生产模式还是开发模式
    mode: "development",
    //打包入口文件
    entry: {
        app: "./src/index.js",
    },
    //打包出口文件
    output: {
        path: path.join(__dirname, "./dist"), //只能使用绝对路径
        filename: "index.js",
    },
    //配置插件
    plugins: [
        new HtmlWebpackPlugin({
            template: path.join(__dirname, "./src/index.html"),
            filename: "index.html",
            inject: true,//是否将入口文件注入到这个html中
        }),
        //主要是为了处理ico文件,因为ico属于特殊文件,
        //不能被webpack自动打包到dist目录下
        new CopyWebpackPlugin({
            patterns: [{
                from: "./src/favicon.ico",
                to: path.join(__dirname, "./dist"),
            }, ],
        }),
    ],
    //配置server
    devServer: {
        compress: true,
        port: 9000,
    },
};

    需要注意的是,插件中使用的路径,特别是带有输出含义的路径,需要使用绝对路径,因此引入了path模块。为什么不直接将html文件作为入口文件呢,那还不用去迁移,这个主要是现在前端再设计上启动项目的一般是一个app.js的项目启动文件,特别是再vue生态下可以看出。另外,为了方便我们快速启动或者打包项目,可以配置npm 脚本信息(脚本工作原理之前说过,这个就不再赘述了):

  "build": "npx webpack",
  "start": "npx webpack-dev-server"

2.webpack引入art-template

    为了更好的方便理解和使用node.js,我们来搭建一个node.js的后台环境,算作是一种实战吧,期间将用到art-template模板。加下来说一下如何利用webpack来导入art-template模板,参考官网:(art-template):
(1)下载art-template模板引擎,需要安装art-templateart-template-loader两个依赖,后者是方便使用webpack对项目进行打包;
(2)为了方便快速刷新我们配置webpack-dev-serverclean-webpack-plugin第三方依赖,前者自动重启服务,后者每次重启自动删除并重新创建dist文件;
(3)接下来调整项目结构和webpack.config.js文件:
在这里插入图片描述

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
    mode: "development",
    devtool: "source-map",
    //用来快速准确定位bug的位置,
    //默认打包会使得bug的位置和实际的位置有偏差
    
    //打包入口文件
    entry: {
        app: "./src/app.js",
    },
    //打包出口文件
    output: {
        path: path.join(__dirname, "./dist"), //只能使用绝对路径
        filename: "app.js",
    },
    //导入art-temlate-loader
    module: {
        rules: [
            // 模板文件
            {
                test: /\.art$/,
                loader: "art-template-loader",
            },
        ],
    },
    //配置插件
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template: path.join(__dirname, "./public/index.html"),
            filename: "index.html",
            inject: true,
        }),
        new CopyWebpackPlugin({
            patterns: [{
                from: "./public/favicon.ico",
                to: path.join(__dirname, "./dist"),
            }, ],
        }),
    ],
    //配置server
    devServer: {
        // contentBase: path.join(__dirname, "./dist"),
        compress: true,
        port: 9000,
    },
};

    配置的时候遇到了一个坑,如果将views目录放置到src目录下,将会导致node_modules的使用出错,因为默认情况下art-template的views文件是放在根目录下的。具体怎么自定义还没有查出来,就放在根目录下吧。

3.项目路由初始化

    为了节省前台的开发精力,使用(AdminLTE后端模板)里面的页面,同时为了方便管理路由,使用(sme-router),这个路由依赖类似于express框架。因为涉及到的代码比较多,简单说一下开发思路和里面的关键代码:
(1)首先项目依旧使用经典的RMVC模式设计;
(2)另外再来捋一下当前各种依赖的作用:

"devDependencies": {
        "art-template-loader": "^1.4.3",//模板引擎打包loader
        "clean-webpack-plugin": "^4.0.0",//用来快速刷新dist目录
        "copy-webpack-plugin": "^10.2.4",//用来复制文件到指定位置
        "html-webpack-plugin": "^5.5.0",//用来处理html页面并执行注入
        "webpack": "^5.68.0",//用来打包项目
        "webpack-cli": "^4.9.2",//打包工具自己的依赖
        "webpack-dev-server": "^4.7.4"//用来自动重启服务
    },
    "dependencies": {
        "art-template": "^4.13.2",//模板引擎
        "jquery": "^3.6.0",//juery
        "sme-router": "^0.12.8"//路由工具
    }
    //其他
    source-map//方便快速查看bug
    AdminLTE//基于bootstrap的模板,减小前端工作量

(3)简单展示一下项目的结构:
在这里插入图片描述
    说明:在views文件中存放剥离掉html和body标签的html代码块,在index.html中设置代码块对应的“插座” <div id="root"></div>

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>测试首页</title>

    <!-- Google Font: Source Sans Pro -->
    <!-- <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback"> -->
    <!-- Font Awesome -->
    <link rel="stylesheet" href="./libs/css/all.min.css">
    <link rel="stylesheet" href="./libs/css/ionicons.min.css">
    <link rel="stylesheet" href="./libs/css/icheck-bootstrap.min.css">
    <link rel="stylesheet" href="./libs/css/adminlte.min.css">
    <link rel="stylesheet" href="./libs/webfonts/font.css">
    <link rel="stylesheet" href="./libs/css/jqvmap.min.css">
    <link rel="stylesheet" href="./libs/css/OverlayScrollbars.min.css">
    <link rel="stylesheet" href="./libs/css/tempusdominus-bootstrap-4.min.css">
    <link rel="stylesheet" href="./libs/css/summernote-bs4.min.css">
    <link rel="stylesheet" href="./libs/css/daterangepicker.css">
    <link rel="stylesheet" href="./libs/webfonts/fa-regular-400.woff2">
    <link rel="stylesheet" href="./libs/webfonts/fa-solid-900.woff2">
    <style>
        .login-page {
            align-items: center;
            background-color: #e9ecef;
            display: -ms-flexbox;
            display: flex;
            -ms-flex-direction: column;
            flex-direction: column;
            height: 100vh;
            -ms-flex-pack: center;
            justify-content: center;
        }
    </style>
</head>

<body class="hold-transition sidebar-mini">
    <div id="root"></div>
    <!-- jQuery -->
    <script src="./libs/js/jquery.min.js"></script>
    <!-- Bootstrap 4 -->
    <script src="./libs/js/bootstrap.bundle.min.js"></script>
    <!-- AdminLTE App -->
    <script src="./libs/js/adminlte.min.js"></script>
    <!-- AdminLTE for demo purposes -->
    <script src="./libs/js/demo.js"></script>
</body>

</html>

    libs下面存放各种静态资源依赖,展示webpack配置文件:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
    mode: "development",
    devtool: "source-map",
    //打包入口文件
    entry: {
        "js/app": path.join(__dirname, "./src/app.js"),
    },
    //打包出口文件
    output: {
        path: path.join(__dirname, "./dist"), //只能使用绝对路径
        filename: "[name].js",
    },
    module: {
        rules: [
            // 模板文件
            {
                test: /\.art$/,
                loader: "art-template-loader",
            },
        ],
    },
    //配置插件
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template: path.join(__dirname, "./public/index.html"),
            filename: "index.html",
            inject: true,
        }),
        new CopyWebpackPlugin({
            patterns: [{
                    from: "./public/favicon.ico",
                    to: path.join(__dirname, "./dist"),
                },
                {
                    from: "./public/libs/",
                    to: path.join(__dirname, "./dist/libs/"),
                },
            ],
        }),
    ],
    //配置server
    devServer: {
        compress: true,
        port: 9000,
    },
};

    路由的基本使用:

//src/router/index.js
import SMERouter from "sme-router";
import index from "../controllers/index";
import login from "../controllers/login";
//放入代码块插座
const router = new SMERouter("root");

router.route("/", index);
router.route("/login", login);
export default router;
//src/controllers/index.js
import indexTpl from "../../views/index.art";
const indexHtml = indexTpl({});
const index = (req, res, next) => {
    res.render(indexHtml);
};
export default index;

    需要注意的是配置完成路由之后,路由不会自动匹配,需要使用router.go("/");跳转到指定路由,其次对于模块的导出,需要使用eport default
    这样整个项目的初步搭建就算是完成了,接下来就是后端的路由和数据传输了。对于前端来说,已经写了太多的前端页面了,后端的话其实在thinkPHP的时候也熟悉了简单的CRUD,后端其他笔记等之后有时间再进一步更新,因为要考研了,可能看这些的时间会少一些。如果你看到了这里,很感谢你,因为你的阅读是我更新的动力,其实我自己也没想到,node.js的笔记阅读量会有这么多,最后还得感谢B站古艺散人提供的视频教程。