Koa, Koa-static, Koa-views, pug, materialize

屠昌胤
2023-12-01

写了一个生成license模块,包括前端和后端,只有一个页面,就不想前后端分两个模块,后端用的koa,在koa基础上用了koa-views和koa-static做了前端,最终采用以下技术实现。

HTML/CSS Framework参考https://geekflare.com/best-css-frameworks/#anchor-materialize也先后尝试了一大堆,发现bootstrap已死,Skeleton过于简单了点,等等等,最后选了Materialize

Steps

cd ~/Workspace
mkdir helloworld
cd helloworld
yarn init
yarn add koa
yarn add @koa/router
yarn add koa-views
yarn add koa-static
yarn add koa-body
yarn add pug

package.json

{
  "name": "ls-license",
  "version": "1.0.0",
  "main": "./src/index.js",
  "license": "MIT",
  "type": "module",
  "private": true,
  "scripts": {
    "dev-build": "nodemon build",
    "build": "node build",
    "dev": "nodemon run",
    "run": "node run"
  },
  "dependencies": {
    "@koa/router": "^10.1.1",
    "chalk": "^5.0.0",
    "config": "^3.3.6",
    "fs-extra": "^10.0.0",
    "koa": "^2.13.4",
    "koa-body": "^4.2.0",
    "koa-static": "^5.0.0",
    "koa-views": "^8.0.0",
    "loglevel": "^1.8.0",
    "loglevel-plugin-prefix": "^0.8.4",
    "moment": "^2.29.1",
    "node-rsa": "^1.1.1",
    "pug": "^3.0.2"
  }
}

index.js

import Koa from 'koa';
import KoaBody from 'koa-body';
import serve from 'koa-static';
import views from 'koa-views';
import path from 'path';
import { fileURLToPath } from 'url';
import Routes from './routes/index.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const app = new Koa();
app
  .use(serve(path.resolve(__dirname, './public'), {}))
  .use(
    KoaBody({
      multipart: true,
      formidable: {
        keepExtensions: true,
        maxFileSize: 10485760, //10 * 1024 * 1024,
      },
    })
  )
  .use(views(path.resolve(__dirname, './views'), { extension: 'pug' }))
  .use(Routes.routes())
  .use(Routes.allowedMethods())
  .listen(8888);

routes/index.js

import KoaRouter from '@koa/router';
import { licenseController } from '../controllers/index.js';

const router = new KoaRouter();

router.get('/', async (ctx) => {
  await ctx.render('index', {
    options: {
      smartools: 'Smartools',
      kanzhun: 'Kanzhun!',
      bluepool: 'Bluepoo',
    },
  });
});
router.post('/license', licenseController.issue);

export default router;

index.pug

html 
    head 
        title License Generator
        link( href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet")
        link( 
            type="text/css"
            rel="stylesheet"
            href="css/materialize.min.css"
        )  
        meta(name="viewport" content="width=device-width, initial-scale=1.0")
    body
        div.container
            h1 License Issuer
            div.row
                form.col.s12(action="./license" method="post") 
                    div.row 
                        div.col.s6
                            label System
                            select(name="system")
                                each val, i in options
                                    option(value=i)= val
                        div.col.s6
                            label Years
                            input(type="text" name="years" value="1")
                    div.row
                        div.col.s12
                            label Locators
                            textarea.materialize-textarea(name="locator")
                    div.row
                        div.col.s12
                            button.btn(type="submit") Issue!
        script(src="js/materialize.min.js") 
        script.
            document.addEventListener('DOMContentLoaded', function() {
                var elems = document.querySelectorAll('select');
                var instances = M.FormSelect.init(elems, {});
            });
 类似资料: