nodejs主要表现是 命令式编程
node 是什么?
Node.js 是⼀个 JS 的服务端运行环境,基于 V8,是在 JS 语言规范的基础上,封装了一些服务端的 runtime,让我们能够简单实现非常多的业务功能。
Node.js 在 2009 年(第一版 npm 被创建)诞生之初是为了实现高性能的 web 服务器,再后来 Node.js 慢慢演化为了一门服务器“语言”。
-
commonJs是一个 规范,nodejs是commonJs的 实现; -
LAMP - Linux + Apache + MySQL + php; (thinkPhP, CI); -
MEAN - mongoDB + express + angular + node.js 2014 年;
node 能做哪些事情?
npm run start 运行了 node;
- 跨平台开发:
PC、web、H5、RN、Weex; - 后端开发:
API、RPC; - 前端开发:前端工具链;
- 工具开发:脚本、脚手架、命令行;
{
"name": "node_basic",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"build": "rollup -c -w"
},
"devDependencies": {
"rollup": "^2.70.2"
}
}
如上 json 配置,如果 rollup 是本地安装,不是全局安装,直接在控制台执行 npm run build 可以执行,如果执行 rollup -c -w 不可以,需要执行 ./node_modules/.bin/rollup -c -w;
分类举例
- 压缩:
UglifyJS、JSMin; - 管理:
npm、yarn、bower; - 模块系统:
Commonjs、ESM; - 模块构建:
Babel、Browserify、Webpack、Gulp、Grunt;
问题
- 单线程很脆弱,但是可以通过
cluster/pm2多核并发实现负载均衡; node对MongoDB、Mysql、redis支持比较好;对neo4j、tigerGraph支持不太好;- 安全问题;
和浏览器的区别
Node环境中是没有DOM、BOM,同样的,浏览器中也没有fs、path这些模块;why?如果浏览器支持fs会怎么样?—— 存在安全问题;
cjs和esmesm值引用、cjs值拷贝;Node.js使用CommonJS模块系统,而在浏览器中我们开始看到正在实施的ESM标准;
具体的内核
node 安装
nvm:是一个node版本管理工具;nrm:用于对node镜像源进行设置;
npm 相关
npm 的目标?
给你和你的团队、你的公司带来最好的开源库和依赖。
npm install 工作原理
npm 缓存
npm config get cache
# 或者
yarn cache dir
npm CI
和 npm install 不同的是:
- 必须要有
package-lock.json文件,且下载完全依赖该文件; - 会删除
node_modules; - 如果和
package.json冲突,则直接报错; - 只能一次性安装;
- 永不改写
package.json和package-lock.json文件;
npm 的包依赖关系
xxxDependencies
比如,我们要构建一个 公共组件库 luyi-ui;
dependencies 项目依赖(常用)
lodash (debounce、deepMerge)
devDependencies 开发依赖(常用)
webpack、rollup、jest
peerDependencies 同版本依赖(常用)
-
vue -
例如
vue组件库;如果说你连vue都没有,那这个项目对你来说没有意义
bundledDependencies 捆绑依赖
{
bundle1, bundle2
}
optionalDependencies 可选依赖
- 可选依赖
element-ui 的 package.json
{
"name": "element-ui",
"version": "2.15.10",
"description": "A Component Library for Vue.js.",
"main": "lib/element-ui.common.js",
"files": ["lib", "src", "packages", "types"],
"typings": "types/index.d.ts",
"scripts": {
"bootstrap": "yarn || npm i",
"build:file": "node build/bin/iconInit.js & node build/bin/build-entry.js & node build/bin/i18n.js & node build/bin/version.js",
"build:theme": "node build/bin/gen-cssfile && gulp build --gulpfile packages/theme-chalk/gulpfile.js && cp-cli packages/theme-chalk/lib lib/theme-chalk",
"build:utils": "cross-env BABEL_ENV=utils babel src --out-dir lib --ignore src/index.js",
"build:umd": "node build/bin/build-locale.js",
"clean": "rimraf lib && rimraf packages/*/lib && rimraf test/**/coverage",
"deploy:build": "npm run build:file && cross-env NODE_ENV=production webpack --config build/webpack.demo.js && echo element.eleme.io>>examples/element-ui/CNAME",
"deploy:extension": "cross-env NODE_ENV=production webpack --config build/webpack.extension.js",
"dev:extension": "rimraf examples/extension/dist && cross-env NODE_ENV=development webpack --watch --config build/webpack.extension.js",
"dev": "npm run bootstrap && npm run build:file && cross-env NODE_ENV=development webpack-dev-server --config build/webpack.demo.js & node build/bin/template.js",
"dev:play": "npm run build:file && cross-env NODE_ENV=development PLAY_ENV=true webpack-dev-server --config build/webpack.demo.js",
"dist": "npm run clean && npm run build:file && npm run lint && webpack --config build/webpack.conf.js && webpack --config build/webpack.common.js && webpack --config build/webpack.component.js && npm run build:utils && npm run build:umd && npm run build:theme",
"i18n": "node build/bin/i18n.js",
"lint": "eslint src/**/* test/**/* packages/**/* build/**/* --quiet",
"pub": "npm run bootstrap && sh build/git-release.sh && sh build/release.sh && node build/bin/gen-indices.js",
"test": "npm run lint && npm run build:theme && cross-env CI_ENV=/dev/ BABEL_ENV=test karma start test/unit/karma.conf.js --single-run",
"test:watch": "npm run build:theme && cross-env BABEL_ENV=test karma start test/unit/karma.conf.js"
},
"faas": [
{
"domain": "element",
"public": "temp_web/element"
},
{
"domain": "element-theme",
"public": "examples/element-ui",
"build": ["yarn", "npm run deploy:build"]
}
],
"repository": {
"type": "git",
"url": "git@github.com:ElemeFE/element.git"
},
"homepage": "http://element.eleme.io",
"keywords": ["eleme", "vue", "components"],
"license": "MIT",
"bugs": {
"url": "https://github.com/ElemeFE/element/issues"
},
"unpkg": "lib/index.js",
"style": "lib/theme-chalk/index.css",
"dependencies": {
"async-validator": "~1.8.1",
"babel-helper-vue-jsx-merge-props": "^2.0.0",
"deepmerge": "^1.2.0",
"normalize-wheel": "^1.0.1",
"resize-observer-polyfill": "^1.5.0",
"throttle-debounce": "^1.0.1"
},
"peerDependencies": {
"vue": "^2.5.17"
},
"devDependencies": {
"@vue/component-compiler-utils": "^2.6.0",
"algoliasearch": "^3.24.5",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-istanbul": "^4.1.1",
"babel-plugin-module-resolver": "^2.2.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-vue-jsx": "^3.7.0",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-2": "^6.24.1",
"babel-regenerator-runtime": "^6.5.0",
"chai": "^4.2.0",
"chokidar": "^1.7.0",
"copy-webpack-plugin": "^5.0.0",
"coveralls": "^3.0.3",
"cp-cli": "^1.0.2",
"cross-env": "^3.1.3",
"css-loader": "^2.1.0",
"es6-promise": "^4.0.5",
"eslint": "4.18.2",
"eslint-config-elemefe": "0.1.1",
"eslint-loader": "^2.0.0",
"eslint-plugin-html": "^4.0.1",
"eslint-plugin-json": "^1.2.0",
"file-loader": "^1.1.11",
"file-save": "^0.2.0",
"gulp": "^4.0.0",
"gulp-autoprefixer": "^6.0.0",
"gulp-cssmin": "^0.2.0",
"gulp-sass": "^4.0.2",
"highlight.js": "^9.3.0",
"html-webpack-plugin": "^3.2.0",
"json-loader": "^0.5.7",
"json-templater": "^1.0.4",
"karma": "^4.0.1",
"karma-chrome-launcher": "^2.2.0",
"karma-coverage": "^1.1.2",
"karma-mocha": "^1.3.0",
"karma-sinon-chai": "^2.0.2",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "^0.0.32",
"karma-webpack": "^3.0.5",
"launch-editor-middleware": "^2.3.0",
"markdown-it": "^8.4.1",
"markdown-it-anchor": "^5.0.2",
"markdown-it-chain": "^1.3.0",
"markdown-it-container": "^2.0.0",
"mini-css-extract-plugin": "^0.4.1",
"mocha": "^6.0.2",
"node-sass": "^4.11.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"postcss": "^7.0.14",
"progress-bar-webpack-plugin": "^1.11.0",
"rimraf": "^2.5.4",
"sass-loader": "^7.1.0",
"select-version-cli": "^0.0.2",
"sinon": "^7.2.7",
"sinon-chai": "^3.3.0",
"style-loader": "^0.23.1",
"transliteration": "^1.1.11",
"uglifyjs-webpack-plugin": "^2.1.1",
"uppercamelcase": "^1.1.0",
"url-loader": "^1.0.1",
"vue": "2.5.21",
"vue-loader": "^15.7.0",
"vue-router": "^3.0.1",
"vue-template-compiler": "2.5.21",
"vue-template-es2015-compiler": "^1.6.0",
"webpack": "^4.14.0",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.11",
"webpack-node-externals": "^1.7.2"
}
}
commonJS 模块化
手写一个 cjs 规范 require
步骤 1
./module.js
module.exports = function () {
return 'hello world';
};
./index.js
// 执行 require 会报错,ReferenceError: require is not defined
// const hello = require('./module.js');
// console.log(`hello luyi, ${hello()}`);
// 可以执行,输出 hello test
console.log('hello test');
./require.js
const { readFileSync } = require('fs');
const { Script } = require('vm');
const path = require('path');
const file = path.resolve(__dirname, './index.js');
const fileContent = readFileSync(file, 'utf-8');
// Script 是编译 js 代码的字符串
const scripts = new Script(fileContent);
// 在当前 global 对象的上下文中运行 vm.Script 包含的编译代码
const res = scripts.runInThisContext();
步骤 2
./index.js
const hello = require('./module.js');
console.log(`hello luyi, ${hello()}`);
./require.js
const { readFileSync } = require('fs');
const { Script } = require('vm');
const path = require('path');
const file = path.resolve(__dirname, './index.js');
const fileContent = readFileSync(file, 'utf-8');
const wrappedContent = `(function(require, module, exports) {
${fileContent}
})`;
// console.log('wrappedContent ===== ', wrappedContent);
/*
输出的是函数体的字符串
(function (require, module, exports) {
const hello = require('./module.js');
console.log(`hello luyi, ${hello()}`);
});
*/
// Script 是编译 js 代码的字符串
const scripts = new Script(wrappedContent);
// 在当前 global 对象的上下文中运行 vm.Script 包含的编译代码
const res = scripts.runInThisContext();
// console.log(res); // 输出的是匿名函数 [Function (anonymous)]
// 下一步要执行这个匿名函数 res()
步骤 3
./require.js
const { readFileSync } = require('fs');
const { Script } = require('vm');
const path = require('path');
function my_require(filename) {
const file = path.resolve(__dirname, filename);
const fileContent = readFileSync(file, 'utf-8');
const wrappedContent = `(function(require, module, exports) {
${fileContent}
})`;
// console.log('wrappedContent ===== ', wrappedContent);
/*
输出的是函数体的字符串
(function (require, module, exports) {
const hello = require('./module.js');
console.log(`hello luyi, ${hello()}`);
});
*/
// Script 是编译 js 代码的字符串
const scripts = new Script(wrappedContent);
// 在当前 global 对象的上下文中运行 vm.Script 包含的编译代码
const res = scripts.runInThisContext();
// console.log(res); // 输出的是匿名函数 [Function (anonymous)]
// 下一步要执行这个匿名函数 res()
const module = {
exports: {},
};
// res 是上面的那个包裹着文件的得到的函数
res(my_require, module, module.exports);
// 外部 require 的结果,就是内部 module.exports 的东西,module.exports 是个对象引用
return module.exports;
}
步骤 4
./index.js
const hello = my_require('./module.js');
console.log(`hello luyi, ${hello()}`);
./require.js
const { readFileSync } = require('fs');
const { Script } = require('vm');
const path = require('path');
function my_require(filename) {
const file = path.resolve(__dirname, filename);
const fileContent = readFileSync(file, 'utf-8');
const wrappedContent = `(function(require, module, exports) {
${fileContent}
})`;
// console.log('wrappedContent ===== ', wrappedContent);
/*
输出的是函数体的字符串
(function (require, module, exports) {
const hello = require('./module.js');
console.log(`hello luyi, ${hello()}`);
});
*/
// Script 是编译 js 代码的字符串
const scripts = new Script(wrappedContent);
// 在当前 global 对象的上下文中运行 vm.Script 包含的编译代码
const res = scripts.runInThisContext();
// console.log(res); // 输出的是匿名函数 [Function (anonymous)]
// 下一步要执行这个匿名函数 res()
const module = {
exports: {},
};
// res 是上面的那个包裹着文件的得到的函数
res(my_require, module, module.exports);
// 外部 require 的结果,就是内部 module.exports 的东西,module.exports 是个对象引用
return module.exports;
}
global.my_require = my_require;
my_require('./index.js');