惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
Webroot Blog
Webroot Blog
博客园 - 叶小钗
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 【当耐特】
Hugging Face - Blog
Hugging Face - Blog
美团技术团队
云风的 BLOG
云风的 BLOG
IT之家
IT之家
S
Secure Thoughts
U
Unit 42
G
GRAHAM CLULEY
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
N
News and Events Feed by Topic
The Cloudflare Blog
月光博客
月光博客
V
Visual Studio Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Schneier on Security
Schneier on Security
O
OpenAI News
Hacker News - Newest:
Hacker News - Newest: "LLM"
P
Privacy International News Feed
The Hacker News
The Hacker News
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
Tailwind CSS Blog
SecWiki News
SecWiki News
M
MIT News - Artificial intelligence
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Simon Willison's Weblog
Simon Willison's Weblog
Stack Overflow Blog
Stack Overflow Blog
爱范儿
爱范儿
Last Week in AI
Last Week in AI
C
Check Point Blog
D
Docker
Scott Helme
Scott Helme
Engineering at Meta
Engineering at Meta
博客园_首页
W
WeLiveSecurity
MongoDB | Blog
MongoDB | Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Vulnerabilities – Threatpost
D
Darknet – Hacking Tools, Hacker News & Cyber Security
J
Java Code Geeks
NISL@THU
NISL@THU
S
Security Affairs
C
Cybersecurity and Infrastructure Security Agency CISA
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

I'm OWenT

国产大模型(GLM 5.1、Kimi K2.6)真实场景效果和 Coding Plan 额度测试 新版本libatapp的连接管理——从etcd服务发现到拓扑驱动的自动重连 新版本libatbus的设计变更——从树形路由到拓扑驱动 Protobuf又一坑 - C++标准和ABI兼容性 AI真好用-给Blog主题统一加mermaid,chart.js,excalidraw,draw.io的多种引入方式支持 给内网部署Squid-通用HTTP下载缓存 UE使用CodeChecker和clang-tidy生成静态分析报告 找出UE的循环依赖 C++小协程栈和临时变量及作用域的栈溢出问题分析 游戏服务的可观测性能力建设(C++生态) 指标上报的多线程优化和多拉取源点优化 协程(libcopp)的Channel功能和CPU命中率优化 通用RPC代码生成器 实现strong_rc_ptr(比shared_ptr更快的引用计数智能指针) 手夯一个STL allocator和对象内存分析组件 std::condition_variable 的信号丢失问题 踩坑一处(GCC)STL std::async 实现BUG导致的crash问题 GCC 14的一个warning to error BUG 给xresloader(Excel导表工具)增强UE读表支持(包含蓝图,Blueprint) Opentelemetry社区在gRPC的几个链接问题(静态库和动态库混用,musl工具链,符号裁剪) Excel转表工具(xresloader)的新验证器(验证外部Excel和文本数据,唯一性和自定义规则) protobuf v22和gRPC v1.55版本升级的依赖变化和upb适配 关于protobuf近期版本(v20/v3.20+)和 gRPC v1.54版本在某些编译环境下的一些链接和编译问题 xresloader-Excel导表工具链的近期变更汇总 打通游戏服务端框架的C++20协程改造的最后一环 Opentelemetry-cpp的Logs模块标准更新(涉及近期版本:1.8-1.9的BREAK CHANGES) 给cmake-toolset和工具链(curl等)加HTTP/2和HTTP/3支持 又开新坑之 coredns 插件: nftables和filter 关于opentelemetry-cpp社区对于C++ Head Only组件单例和符号可见性的讨论小记 填个转表工具 xresloader 去年的坑(数组尾部裁剪) 集成 upb 和 lua binding 的踩坑小记 libcopp对C++20协程的接入和接口设计 再度优化GCC、LLVM、Clang、libc++、libc++abi等套件的构建脚本 游戏服务的分布式事务优化(二)- 事务管理 游戏服务的分布式事务优化(一)- Write Ahead Log(WAL) 模块 记录一些bazel适配用编译选项 测试现代化硬件C++浮点数性能和一致性 适配Boringssl和OpenSSL 3.0 近期cmake-toolset的一些适配问题 C++20 Text Formatting/fmtlib 适配问题小记 再次重构LLVM+Clang+libcxx+libc++abi+其他相关工具的构建流程 重构基于CMake的构建工具链 新版GCC和LLVM+Clang终于Release啦 折腾一下nftables下的双拨 [C++20] Module partitions和符号交叉引用(声明和实现分离) [Rust] 实现一个线程安全且迭代器可以保存的链表 基于protobuf的代码生成 几个使用protobuf中C++接口的Arena的坑 Amazon Aurora DB存储引擎论文阅读小记 近期对libatapp的一些优化调整(增加服务发现和连接管理,支持yaml等) xresloader转表工具链增加了一些新功能(map,oneof支持,输出矩阵,基于模板引擎的加载代码生成等) 在游戏服务器中使用分布式事务 libcopp接入C++20 Coroutine和一些过渡期的设计 libatbus 的大幅优化 nftables初体验 容器配置开发环境小计 PALM Tree - 适合多核并发架构的B+树 - 论文阅读小记 跨平台协程库 - libcopp 简介 C++20 Coroutine 性能测试 (附带和libcopp/libco/libgo/goroutine/linux ucontext对比) 尝鲜Github Action 一些xresloader(转表工具)的改进 protobuf、flatbuffer、msgpack 针对小数据包的简单对比 协程框架(libcopp) 小幅优化 Excel转表工具(xresloader) 增加protobuf插件功能和集成 UnrealEngine 支持 Anna(支持任意扩展和超高性能的KV数据库系统)阅读笔记 C++20 Coroutine libcopp merge boost.context 1.69.0 Google去中心化分布式系统论文三件套(Percolator、Spanner、F1)读后感 Rust玩具-企业微信机器人通用服务 使用ELK辅助监控开发测试环境服务质量和问题定位 2018年的新通用伪随机数算法(xoshiro / xoroshiro)的C++(head only)实现 Rust的第二次接触-写个小服务器程序 理解和适配AEAD加密套件 atsf4g-co的进化:协程框架v2、对象路由系统和一些其他细节优化 协程框架(libcopp)v2优化、自适应栈池和同类库的Benchmark对比 可执行文件压缩 初识Rust 使用restructedtext编写xresloader文档 atframework的etcd模块化重构 C++的backtrace ECDH椭圆双曲线(比DH快10倍的密钥交换)算法简介和封装 protobuf-net的动态Message实现 pbc的proto3接入 atgateway内置协议流程优化-加密、算法协商和ECDH 整理一波软件源镜像同步工具+DevOps工具 Blog切换到Hugo libcopp v2的第一波优化完成 libcopp(v2) vs goroutine性能测试 libcopp的线程安全、栈池和merge boost.context 1.64.0 GCC 7和LLVM+Clang+libc++abi 4.0的构建脚本 libatbus的几个藏得很深的bug 用cmake交叉编译到iOS和Android 开源项目得一些小维护 atapp的c binding和c#适配 对象路由系统设计 2016年总结 近期的一个协程流程BUG 重写了llvm+clang+libc++和libc++abi的构建脚本 atsf4g完整游戏工程示例|I'm OWenT atframework基本框架已经完成|I'm OWenT
Webpack+vue+boostrap+ejs构建Web版GM工具
owent · 2018-10-17 · via I'm OWenT

blog-website

前言

Web前端的组件技术刷新真的是日新月异,前段时间看到很多童鞋分享了webpack的使用,刚好之前做我们游戏里Web版的GM工具的时候正在想怎么用简单的方式,做模块分离并且又不需要引入重量级的第三方库或组件,也不需要太繁琐的流程(毕竟只是个小工具)。

我们的Web版GM工具长差不多这个样子,全静态页面。

1811-01.png

1811-02.png

因为分成了好几个模块,然后由于用的是bootstrap的。上面的Tab和下面的内容还有处理逻辑的函数都分了三大块,在不同的位置。在内容持续增加以后,全都写在一个html里太不方便了,而如果走ajax加载,调试和本地编辑都挺麻烦。

安装webpack比较简单,直接走npm命令即可。

npm install webpack webpack-cli --save-dev

当然如果想要换源或者用 tnpm 或者cnpm,把上面的npm命令替换一下就行了。

后面的很多组件都涉及 webpack 的支持包,也都是需要额外安装的。

自动适配浏览器的ES6支持: babel

现在ES版本很高了,开启一些新特性的支持试很爽的,但是浏览器兼容性怎么办呢?上 babel。当然还得加上 webpack 支持。

npm install babel-core babel-loader babel-preset-env --save-dev

还可以加上VSCode的提示tags支持。

npm install @babel/core @babel/preset-env --save

然后 webpack 模具哎规则里加上:

{
    test: /\.js$/,
    exclude: /(node_modules|bower_components)/,
    use: {
        loader: 'babel-loader',
        options: {
            presets: ['env']
        }
    }
}

sass、css支持

为了可以方便地使用css,可以加入 sass 或者 less 支持,我这里加入了 sass 支持。然后再加上原本的css模块。

npm install css-loader sass-loader style-loader node-sass --save-dev

然后 webpack 模具哎规则里加上:

{
    test: /\.css$/,
    use: ['vue-style-loader', 'style-loader', 'css-loader']
},
{
    test: /\.scss$/,
    use: [
        "vue-style-loader", // Vue支持,后面会提到
        "style-loader", // creates style nodes from JS strings
        "css-loader", // translates CSS into CommonJS
        "sass-loader" // compiles Sass to CSS, using Node Sass by default
    ]
},
{
    test: /\.sass$/,
    use: [
        'vue-style-loader', // Vue支持,后面会提到
        "style-loader",
        'css-loader',
        {
            loader: 'sass-loader',
            options: {
                indentedSyntax: true
            }
        }
    ]
}

Vue模板

我的GM工具中使用Vue做模板引擎,前面有提到Vue模板引擎的支持。首先也是安装基础库的支持库。

npm install vue --save
npm install vue-loader --save-dev

不过其实我没有使用 vue-loader 来提供.vue后缀的支持。感觉这种方式局限性比较高。我用的是运行时编译的版本,而 vuewebpack 文档里支持方式是只导入了runtime,没有导入编译库,所以这里初始化流程会麻烦一些。当然如果开 .vue 支持的话可以加规则:

{
    test: /\.vue$/,
    loader: 'vue-loader'
}

插件初始化里要使用完整版本的Vue:

{
  // 。。。
  plugins: [
    new webpack.ProvidePlugin({
      Vue: ['vue/dist/vue.esm.js', 'default']
    }),
    // new VueLoaderPlugin() //开 .vue 支持的话加这一行
  ]
}

HTML模板引擎和ejs

webpack 默认是对js打包的,但是如果能在编译期对html打包才能满足我们GM工具的模块化的需求。其实有很多模板引擎增加了对 webpack 的支持,而我之前用过一些 ejs ,比较轻量级,功能也足够,所以我还是用了 ejs 作为模板系统。 另外要让 webpack 支持对html打包,还需要 html-webpack-plugin 插件:

npm install html-webpack-plugin ejs-loader ejs-webpack-loader --save-dev

这里要注意下 webpack 的版本,这里的插件对不同大版本的 webpack 可能不同。 接下来仍然是注册规则:

{
    test: /\.ejs$/,
    use: ['ejs-webpack-loader']
}

然后初始化:

{
  plugins: [
    new HtmlWebpackPlugin({
      template: '!!ejs-webpack-loader!./src/index.ejs',
      inject: 'body'
    })
  ]
}

额外组件: bootstrap、jquery、moment

bootstrapjquerymoment 是前端页面用到的,然后 bootstrap 还依赖 popper.js

先安装依赖:

npm install bootstrap jquery moment popper.js --save

接下来就比较特殊了,因为 webpack 走的是和 node.js 一样的模块隔离,像上面的这些库是需要写入全局命名空间的,所以还需要初始化的时候导入一下:

{
  plugins: [
    new webpack.ProvidePlugin({
      moment: "moment",
      $: "jquery",
      jQuery: "jquery"
    })
  ]
}

集成VSCode: monaco-editor 和 typescript 支持

我们GM工具里内嵌了VSCode的编辑器内核 monaco-editor ,在通用信息查看编辑和diff上还是很有用的。然后由于 monaco-editor 依赖 typescript 就顺便把 typescript 也导入进来了。

安装脚本:

npm install monaco-editor --save
npm install monaco-editor-webpack-plugin typescript vue-ts-loader --save-dev # 顺便安装 vue-ts-loader

规则配置:

{
  test: /\.tsx?$/,
  use: ['vue-ts-loader']
}

插件配置:

{
  plugins: [
    new MonacoWebpackPlugin()
  ]
}

最终配置和编译运行

最终的配置其实还包含一些细节的目录结构、环境信息和构建选项。我们GM工具最终的 webpack.config.js 文件如下:

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// const VueLoaderPlugin = require('vue-loader/lib/plugin');
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');

module.exports = {
    // mode: 'development', //'mode' option to 'development' or 'production'
    entry: './src/js/main.js',
    output: {
        path: __dirname + '/dist/',
        filename: 'bundle.js'
    },
    devServer: {
        inline: false,
        contentBase: "./dist",
    },
    devtool: "cheap-module-source-map",
    module: {
        rules: [{
                test: /\.ejs$/,
                use: ['ejs-webpack-loader']
            },
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['env']
                    }
                }
            },
            {
                test: /\.tsx?$/,
                use: ['vue-ts-loader']
            },
            {
                test: /\.css$/,
                use: ['vue-style-loader', 'style-loader', 'css-loader']
            },
            {
                test: /\.scss$/,
                use: [
                    "vue-style-loader",
                    "style-loader", // creates style nodes from JS strings
                    "css-loader", // translates CSS into CommonJS
                    "sass-loader" // compiles Sass to CSS, using Node Sass by default
                ]
            },
            {
                test: /\.sass$/,
                use: [
                    'vue-style-loader',
                    "style-loader",
                    'css-loader',
                    {
                        loader: 'sass-loader',
                        options: {
                            indentedSyntax: true
                        }
                    }
                ]
            },
            // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            }
        ]
    },
    plugins: [
        new webpack.ProvidePlugin({
            moment: "moment",
            $: "jquery",
            jQuery: "jquery",
            Vue: ['vue/dist/vue.esm.js', 'default']
        }),
        // new VueLoaderPlugin(),
        new HtmlWebpackPlugin({
            template: '!!ejs-webpack-loader!./src/index.ejs',
            inject: 'body'
        }),
        new MonacoWebpackPlugin()
    ]
}

typescript配置文件 tsconfig.json 的配置如下:

{
    "compilerOptions": {
        "target": "es5",
        "module": "es2015",
        "moduleResolution": "node",
        "declaration": false,
        "noImplicitAny": true,
        "removeComments": true,
        "preserveConstEnums": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "sourceMap": true,
        "typeRoots": [
            "node_modules/@types"
        ],
        "lib": [
            "es2017",
            "dom"
        ]
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "node_modules"
    ]
}

然后 package.json 里增加了脚本命令:

{
  "scripts": {
    "dev": "webpack --mode development",
    "build": "webpack --mode production"
  }
}

最后,编译打包的时候只要运行 npm run devnpm run build 就可以了。