Node Typescript打包发布

使用rollup打包typscript-node项目为第三方库 tsc和rollup对比 tsc是Typescript官方的编译器,本身也具有打包功能,但是其本质只是编译器,它适合于打包直接运行的大型项目文件,并不适合构建独立的第三方库或组件。 rollup则是javascript打包器,它可以将ES6模块打包称单个javascript文件,同时它本身也采用了Tree Shaking优化算法,能使得打包文件大小得到进一步的优化。 另一方面,rollup支持插件功能,通过设置插件能满足大部分时候的打包需求,在下面即将要讲解的打包中,插件提供了很大的帮助。RollUp插件集合网站 rollup打包流程 本地安装 rollup 就我个人而言,不推荐安装全局的rollup包,因为在协同工作时,这样会导致rollup版本得不到统一而产生打包错误,所以推荐在本地安装rollup,本文使用的包管理工具为yarn,安装命令如下: yarn add rollup 安装完毕后,在package.json文件里设置对应的脚本,用于快速启动打包。 // package.json { "scripts": { "build": "rollup -c" } } -c的意思是按照配置文件中设置的内容进行打包。 设置rollup.config.js文件 就如同tsconfig.json一样,rollup也是有一个对应的配置文件名为rollup.config.js,虽然其不是必须的,但配置文件强大且方便,所以在配置项目打包时基本都要用到配置文件。 在项目根目录创建对应的配置文件,在文件里根据自己的需求来编写对应的配置代码。 rollup.config.js是一个ES模块,它会根据文件内导出的内容来进行打包上的设置,如下所示。 // rollup.config.js export default { // 这里也可以是一个数组 input: [], output: [], external: [], plugins: [], // .... } 安装插件 需要三个插件: rollup-plugin-typescript2 => 将typescript转移为javascript的插件 rollup/plugin-commonjs => 将commonjs语法转换为es6 rollup-plugin-dts => 生成声明文件d.ts文件 执行以下的命令 yarn add @rollup/plugin-commonjs rollup-plugin-typescript2 typescript tslib rollup-plugin-dts --dev 修改配置文件 关于配置文件的各个变量配置这里不赘述,如有需求,可查阅rollup官网的配置说明。 // rollup....

May 7, 2023 · 2 min · 259 words · Runtus

Functional_Program_3

关于副作用以及外部引用与函数式编程的关系 Pure Happiness with Pure Functions 禁止与外界交互 在第二章中也有说到,保持纯函数的关键在于不能与外界有直接交互,即直接引用。 这样有个好处是能让函数能够自给自足,从而能够只看函数本身就能更加轻松了解到函数本身的功能,而不需要借助外部变量来理解,例如以下的例子。 let minimum = 21 const checkAge = age => age => minium checkage依赖与外部变量minium,假如该变量声明的位置很远,当后续维护时会对这段代码返回的结果感到匪夷所思,不知道其值到底从何而来。 副作用 对于函数而言,函数的副作用就是函数执行时对外界环境产生了影响(无论是依赖还是修改)。 上述的与外界交互也算是副作用的一种,副作用在计算机领域并不是贬义的含义,只是对代码执行过程的一种结果的描述,只不过在函数式编程中,副作用被视为不好的程序过程执行。 下面列举了一些副作用的例子。 更改文件fs 数据库访问 发起http请求 DOM控制 获取系统状态 获取用户的输入 so on….. 并不是说在函数式编程中,我们要完全拒绝以上操作,而是要能控制这一系列操作。后续会介绍如何去进行这一个控制过程(柯里化),下面先介绍如何将纯函数从一个普通的函数中分离出来。 纯函数的分离 一个对外界依赖的函数要分离成纯函数,就必须要显式告知函数要依赖的对象是谁,即把要依赖的对象作为参数传递,从而将外部依赖改为内部依赖。 // 不纯函数,其没有显示告知函数依赖的对象是谁。 const signUp = (attrs) => { const user = saveUser(attrs); welcomeUser(user); }; // pure -> 将DB,Email显示告知 const signUp = (Db, Email, attrs) => () => { const user = saveUser(Db, attrs); welcomeUser(Email, user); }; 这样做的好处不仅仅是让函数的依赖关系更加明确从而使得函数可读性增强,而且还让函数的复用性增强,一旦Db或Email有变化,只需要重新设置这两参数,再获取一个SignUp即可。

March 23, 2023 · 1 min · 74 words · Runtus

Functional_Program

读 Professor Frisby’s Mostly Adequate Guide to Functional Programming 记录 Functional Programming原文链接 本章主要简单介绍函数式编程中的一等公民,以及函数式编程的一些注意事项和好处。 第二章: First Class Functions 在函数式编程中,函数是作为一等公民存在的,应该把函数和其他变量等同,即函数也是变量,变量的类型也可以是函数,函数的参数也可以是函数。 const hi = name => `Hi, ${name}` const greeting = hi hi("小明"); 常见的回调函数,其实就是把函数当作参数传递。 const callback = (...args) => { // balabala } ajax("/xianbei114514/1919810", callback) 不要做无所谓的函数返回 在写代码时,有时会做无意义的操作,在一个函数中,将另一个函数返回。其实它们的功能都没有变化,只是换了个变量名而已。 // 不好的操作 const getServerStuff = callback => ajaxCall(json => callback(json)); 对于上述代码,getServerStuff本质就是想传递一个回调函数,并在回调函数中获取ajax请求得到的值,但完全没必要写那么多,它等同于下面代码实现。 // 好的操作 const getServerStuff = ajaxCall; 此时getServerStuff的功能也是传递一个回调函数并获取到ajax的值,这和上面有区别吗?没有区别。 减少代码冗余,增强代码可读性以及可维护性 继续拿上述的ajaxCall例子来说,假如我们传递的回调函数如下所示。 ajaxCall((json) => callback(json)) 这只是一个调用,如果说有多处的ajaxCall都要进行如此的回调函数的传递,那么一旦我们的业务发生改变时,就会去修改每一处代码,并且每次都要写一遍回调函数的形式,显得非常冗余。 所以考虑将函数作为变量来传递。 const cb = (json) => callback(json) ajaxCall(cb) 此时一旦遇到上述情况,直接去修改cb的内容即可,并且代码量也会减少。 禁止this的出现 在函数式编程中,要保证函数是够**“纯”(1,5!)的,即不能让函数内的任何行为影响到函数外,而this指针便是一个例子,this指向的是执行函数的作用域,一旦使用了this,便会导致函数和外界进行交互,从而不纯**。 但在实际生产过程中,有时的业务情况又不得不这样操作,所以不能完全循规蹈矩,而是要懂随机应变,少量的交互并不会影响整体的代码质量。再说一句,若要调用含有this指针的函数,最好先使用bind函数改变this指针指向,这样不仅能让代码更加易读,还能减少一些未来执行时可能遇见的错误。 // 借用网上的例子 // scary fs....

March 21, 2023 · 1 min · 91 words · Runtus
cover

Rust-所有权

所有权系统和引用在Rust中是至关重要的,它的设计使得rust的GC机制与众不同,也让rust获得了性能上的回报。 所有权 所有权:一个数值只能被一个变量所拥有,即该变量唯一拥有该数值,若变量离开了其作用域,数值也会被释放掉。 如果将一个变量赋值给另一个变量,则意味着对应的值的所有权会被移交出去,那么原先的变量将不再拥有值的所有权,这也是为什么在rust中,变量的赋值也叫变量的绑定。 // 例子 fn main(){ let s1 = String::from("Hello"); let s2 = s1; // 所有权移交 -> 即move println!("{}", s1); // 报错 } 可以看到,上述例子的s1将所有权移交给s2后,自己便不再拥有对字符串Hello的控制。 从内存的视角观察 还是上述例子,在内存里表示出来,如下图所示。 可以看出,再进行变量绑定时,s2实际上是s1的浅拷贝结果,但唯一不同的是指针的移交操作,即指针不是单纯的拷贝,而是从s1上“移交”给了s2,这也是一个move的过程。 如果不想让s1的所有权移交出去,则可以调用String的clone方法来实现深拷贝 ,在堆内存上再开辟一个空间,这样两个变量都有对应的值,这样就不会发生变量无法使用的情况了。 let s1 = String::from("hello"); let s2 = s1.clone(); // 直接重新开辟一个空间,尽量少用,会影响rust性能 println!("s1 = {}, s2 = {}", s1, s2); 需要注意的是,这并不能说明存储在堆内存中的数据只能有一个引用(即指针),这里只强调了move这个操作,即所有权的移交过程,而没有说明堆数据只能有一个引用。 Copy类型 之所以提到copy类型是因为它与上述的String类型有所不同,具有Copy属性的数据类型的数据都是直接存储于栈内存中的,即具有copy特征的数据在进行赋值时,旧变量依然可以使用。 fn main(){ let a = 1; let b = a; // 将 a 赋值给 b } 当赋值时,进行了浅拷贝操作,由于简单类型直接在栈上进行浅拷贝,开销小,两个1时存储在不同的栈内存空间里,所以两个变量都有与之对应的数值,所以不会像刚才的String类型一样,发生s1不可使用的情况。...

October 26, 2022 · 1 min · 82 words · Runtus

再拾docker

记录docker的基本概念和用法,系统的再认识一次docker docker是什么 Docker是对Linux容器的一种封装,并提供简单易用的接口,同时它也是目前最流行的Linux容器解决方案。 在docker出现之前,环境移植一直是非常麻烦的事情,当我们需要把项目从一台机器迁移到另一台机器时,不仅仅是迁移源代码,更重要的是要保证环境的一致性,而一次次环境的搭建则显得冗余且效率极低,所以在思考有没有一种方式能够把环境一起进行迁移。 虚拟机的出现在一定程度上解决了这个问题,但接踵而至的问题是: 虚拟机占用资源多,它本质就是一台完整的操作系统, 冗余步骤多,由于是完整的操作系统,一些系统级别的操作步骤不可避免。 启动慢。 所以Linux发展出了另一种虚拟化技术:Linux容器。而docker则是Linux容器的一种解决方案(也是最流行的) 可以简单的将docker理解为一种非常轻量级的虚拟机。 docker镜像(image文件) docker把应用程序及其依赖打包在image文件里,通过image文件,就会生成容器(后续会提到),即镜像文件其实就是容器的模版,而容器则是镜像文件的实例(可以一一对应类与对象) image文件是二进制文件。在实际开发中,我们会在别人写好的image文件上加一些自定义设置从而形成我们需要的image文件,而不是自己从零开发一个image文件(当然,有需求另说)。 # 有关image命令 docker image ls # 列出docker镜像 docker image rm [imageName] # 删除某镜像文件 容器文件 由image生成的容器实例,本身也是一个文件,称为容器文件。同时,当关闭容器时不会删除容器文件,只是让容器停止运行而已。 docker container ls # 本机正在运行的容器 docker container ls --all # 本机所有容器 每个容器都有一个唯一ID,如果需要终结容器的运行,需要使用kill命令docker container kill。 如需要删除容器文件,需要使用rm命令。 docker container rm [containerID]

January 29, 2022 · 1 min · 47 words · Runtus