当前位置: 首页 > news >正文

网站的特征泸州中泸集团建设有限公司网站

网站的特征,泸州中泸集团建设有限公司网站,网站后期维护工作包括哪些,廊坊高端网站建设背景 随着前端复杂度的不断提升#xff0c;诞生出很多打包工具#xff0c;比如最先的grunt#xff0c;gulp。到后来的webpack和Parcel。但是目前很多脚手架工具#xff0c;比如vue-cli已经帮我们集成了一些构建工具的使用。有的时候我们可能并不知道其内部的实现原理。其实… 背景 随着前端复杂度的不断提升诞生出很多打包工具比如最先的gruntgulp。到后来的webpack和Parcel。但是目前很多脚手架工具比如vue-cli已经帮我们集成了一些构建工具的使用。有的时候我们可能并不知道其内部的实现原理。其实了解这些工具的工作方式可以帮助我们更好理解和使用这些工具也方便我们在项目开发中应用。 一些知识点 在我们开始造轮子前我们需要对一些知识点做一些储备工作。 模块化知识 首先是模块的相关知识主要的是 es6 modules 和 commonJS模块化的规范。更详细的介绍可以参考这里 CommonJS、AMD/CMD、ES6 Modules 以及 webpack 原理浅析。现在我们只需要了解 es6 modules 是一个编译时就会确定模块依赖关系的方式。CommonJS的模块规范中Node 在对 JS 文件进行编译的过程中会对文件中的内容进行头尾包装 在头部添加(function (export, require, modules, __filename, __dirname){\n 在尾部添加了\n};。这样我们在单个JS文件内部可以使用这些参数。AST 基础知识 什么是抽象语法树 在计算机科学中抽象语法树abstract syntax tree 或者缩写为 AST或者语法树syntax tree是源代码的抽象语法结构的树状表现形式这里特指编程语言的源代码。树上的每个节点都表示源代码中的一种结构。之所以说语法是「抽象」的是因为这里的语法并不会表示出真实语法中出现的每个细节。 大家可以通过Esprima 这个网站来将代码转化成 ast。首先一段代码转化成的抽象语法树是一个对象该对象会有一个顶级的type属性Program,第二个属性是body是一个数组。body数组中存放的每一项都是一个对象里面包含了所有的对于该语句的描述信息: type:描述该语句的类型 --变量声明语句 kind变量声明的关键字 -- var declaration: 声明的内容数组里面的每一项也是一个对象type: 描述该语句的类型 id: 描述变量名称的对象type定义name: 是变量的名字init: 初始化变量值得对象type: 类型value: 值 is tree 不带引号row: \is tree\ 带引号 进入正题 webpack 简易打包 有了上面这些基础的知识我们先来看一下一个简单的webpack打包的过程首先我们定义3个文件 // index.js import a from ./testconsole.log(a)// test.js import b from ./messageconst a hello bexport default a// message.js const b worldexport default b 方式很简单定义了一个index.js引用test.jstest.js内部引用message.js。看一下打包后的代码 (function (modules) {var installedModules {};function __webpack_require__(moduleId) {if (installedModules[moduleId]) {return installedModules[moduleId].exports;}var module installedModules[moduleId] {i: moduleId,l: false,exports: {}};modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);// Flag the module as loadedmodule.l true;// Return the exports of the modulereturn module.exports;}// expose the modules object (__webpack_modules__)__webpack_require__.m modules;// expose the module cache__webpack_require__.c installedModules;// define getter function for harmony exports__webpack_require__.d function (exports, name, getter) {if (!__webpack_require__.o(exports, name)) {Object.defineProperty(exports, name, {enumerable: true, get: getter});}};// define __esModule on exports__webpack_require__.r function (exports) {if (typeof Symbol ! undefined Symbol.toStringTag) {Object.defineProperty(exports, Symbol.toStringTag, {value: Module});}Object.defineProperty(exports, __esModule, {value: true});};// create a fake namespace object// mode 1: value is a module id, require it// mode 2: merge all properties of value into the ns// mode 4: return value when already ns object// mode 8|1: behave like require__webpack_require__.t function (value, mode) {/******/if (mode 1) value __webpack_require__(value);if (mode 8) return value;if ((mode 4) typeof value object value value.__esModule) return value;var ns Object.create(null);__webpack_require__.r(ns);Object.defineProperty(ns, default, {enumerable: true, value: value});if (mode 2 typeof value ! string) for (var key in value) __webpack_require__.d(ns, key, function (key) {return value[key];}.bind(null, key));return ns;};// getDefaultExport function for compatibility with non-harmony modules__webpack_require__.n function (module) {var getter module module.__esModule ?function getDefault() {return module[default];} :function getModuleExports() {return module;};__webpack_require__.d(getter, a, getter);return getter;};// Object.prototype.hasOwnProperty.call__webpack_require__.o function (object, property) {return Object.prototype.hasOwnProperty.call(object, property);};// __webpack_public_path____webpack_require__.p ;// Load entry module and return exportsreturn __webpack_require__(__webpack_require__.s ./src/index.js); })({./src/index.js: (function (module, __webpack_exports__, __webpack_require__) {use strict;eval(__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _test__WEBPACK_IMPORTED_MODULE_0__ __webpack_require__(/*! ./test */ \./src/test.js\);\n\n\nconsole.log(_test__WEBPACK_IMPORTED_MODULE_0__[\default\])\n\n\n//# sourceURLwebpack:///./src/index.js?);}),./src/message.js: (function (module, __webpack_exports__, __webpack_require__) {// ...}),./src/test.js: (function (module, __webpack_exports__, __webpack_require__) {// ...}) }); 看起来很乱没关系我们来屡一下。一眼看过去我们看到的是这样的形式 (function(modules) {// ... })({// ... }) 这样好理解了吧就是一个自执行函数传入了一个modules对象modules 对象是什么样的格式呢上面的代码已经给了我们答案 {./src/index.js: (function (module, __webpack_exports__, __webpack_require__) {// ...}),./src/message.js: (function (module, __webpack_exports__, __webpack_require__) {// ...}),./src/test.js: (function (module, __webpack_exports__, __webpack_require__) {// ...}) } 是这样的一个 路径 -- 函数 这样的 key,value 键值对。而函数内部是我们定义的文件转移成 ES5 之后的代码 use strict; eval(__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _test__WEBPACK_IMPORTED_MODULE_0__ __webpack_require__(/*! ./test */ \./src/test.js\);\n\n\nconsole.log(_test__WEBPACK_IMPORTED_MODULE_0__[\default\])\n\n\n//# sourceURLwebpack:///./src/index.js?); 到这里基本上结构是分析完了接着我们看看他的执行自执行函数一开始执行的代码是 __webpack_require__(__webpack_require__.s ./src/index.js); 调用了__webpack_require_函数并传入了一个moduleId参数是./src/index.js。再看看函数内部的主要实现 // 定义 module 格式 var module installedModules[moduleId] {i: moduleId, // moduleIdl: false, // 是否已经缓存exports: {} // 导出对象提供挂载 };modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 这里调用了我们modules中的函数并传入了__webpack_require__函数作为函数内部的调用。module.exports参数作为函数内部的导出。因为index.js里面引用了test.js所以又会通过__webpack_require__来执行对test.js的加载 var _test__WEBPACK_IMPORTED_MODULE_0__ __webpack_require__(./src/test.js); test.js内又使用了message.js所以test.js内部又会执行对message.js的加载。message.js执行完成之后因为没有依赖项所以直接返回了结果 var b world __webpack_exports__[default] (b) 执行完成之后再一级一级返回到根文件index.js。最终完成整个文件依赖的处理。 整个过程中我们像是通过一个依赖关系树的形式不断地向数的内部进入等返回结果又开始回溯到根。 开发一个简单的 tinypack 通过上面的这些调研我们先考虑一下一个基础的打包编译工具可以做什么 转换ES6语法成ES5处理模块加载依赖生成一个可以在浏览器加载执行的 js 文件第一个问题转换语法其实我们可以通过babel来做。核心步骤也就是 通过babylon生成AST通过babel-core将AST重新生成源码/*** 获取文件解析成ast语法* param filename // 入口文件* returns {*}*/ function getAst (filename) {const content fs.readFileSync(filename, utf-8)return babylon.parse(content, {sourceType: module,}); }/*** 编译* param ast* returns {*}*/ function getTranslateCode(ast) {const {code} transformFromAst(ast, null, {presets: [env]});return code } 接着我们需要处理模块依赖的关系那就需要得到一个依赖关系视图。好在babel-traverse提供了一个可以遍历AST视图并做处理的功能通过 ImportDeclaration 可以得到依赖属性 function getDependence (ast) {let dependencies []traverse(ast, {ImportDeclaration: ({node}) {dependencies.push(node.source.value);},})return dependencies }/*** 生成完整的文件依赖关系映射* param fileName* param entry* returns {{fileName: *, dependence, code: *}}*/ function parse(fileName, entry) {let filePath fileName.indexOf(.js) -1 ? fileName .js : fileNamelet dirName entry ? : path.dirname(config.entry)let absolutePath path.join(dirName, filePath)const ast getAst(absolutePath)return {fileName,dependence: getDependence(ast),code: getTranslateCode(ast),}; } 到目前为止我们也只是得到根文件的依赖关系和编译后的代码比如我们的index.js依赖了test.js但是我们并不知道test.js还需要依赖message.js他们的源码也是没有编译过。所以此时我们还需要做深度遍历得到完成的深度依赖关系 /*** 获取深度队列依赖关系* param main* returns {*[]}*/ function getQueue(main) {let queue [main]for (let asset of queue) {asset.dependence.forEach(function (dep) {let child parse(dep)queue.push(child)})}return queue } 那么进行到这一步我们已经完成了所有文件的编译解析。最后一步就是需要我们按照webpack的思想对源码进行一些包装。第一步先是要生成一个modules对象 function bundle(queue) {let modules queue.forEach(function (mod) {modules ${mod.fileName}: function (require, module, exports) { ${mod.code} },})// ... } 得到 modules 对象后接下来便是对整体文件的外部包装注册requiremodule.exports (function(modules) {function require(fileName) {// ...}require(${config.entry});})({${modules}}) 而函数内部也只是循环执行每个依赖文件的 JS 代码而已完成代码 function bundle(queue) {let modules queue.forEach(function (mod) {modules ${mod.fileName}: function (require, module, exports) { ${mod.code} },})const result (function(modules) {function require(fileName) {const fn modules[fileName];const module { exports : {} };fn(require, module, module.exports);return module.exports;}require(${config.entry});})({${modules}});// We simply return the result, hurray! :)return result; } 到这里基本上也就介绍完了接下来就是输出编译好的文件了这里我们为了可以全局使用tinypack包我们还需要为其添加到全局命令这里直接参考我的源码吧不再赘述了。我们来测试一下 npm i tinypack_demo1.0.7 -gcd examplestinypack 看一下输出的文件 (function (modules) {function require(fileName) {const fn modules[fileName];const module {exports: {}};fn(require, module, module.exports);return module.exports;}require(./src/index.js); })({./src/index.js: function (require, module, exports) {use strict;var _test require(./test);var _test2 _interopRequireDefault(_test);function _interopRequireDefault(obj) {return obj obj.__esModule ? obj : {default: obj};}console.log(_test2.default);}, ./test: function (require, module, exports) {use strict;Object.defineProperty(exports, __esModule, {value: true});var _message require(./message);var _message2 _interopRequireDefault(_message);function _interopRequireDefault(obj) {return obj obj.__esModule ? obj : {default: obj};}var a hello _message2.default;exports.default a;}, ./message: function (require, module, exports) {use strict;Object.defineProperty(exports, __esModule, {value: true});var b world;exports.default b;}, }) 再测试一下 恩基本上已经完成一个建议的 tinypack。 参考文章 抽象语法树 Abstract syntax tree 一看就懂的JS抽象语法树 源码 tinypack 所有的源码已经上传 github 转载于:https://www.cnblogs.com/tiedaweishao/p/9155075.html
http://www.pierceye.com/news/76911/

相关文章:

  • 桂林的网站建设公司h5建站免费
  • 深圳商城网站15年做哪个网站能致富
  • 湛江模板建站哪家好义乌做网站的电话
  • 韩国 网站 域名专业网站建设比较好
  • 哪些网站是做货源的网络seo推广培训
  • 南昌网站定制wordpress 公用模块
  • 口碑营销成功的案例seo任务大厅
  • 企业网站备案信息高端建材品牌
  • 三亚学做网站培训二手车网站开发过程
  • 重庆网站建设建站收费建筑方案设计网站
  • 衡水做网站推广找谁苏州市网站制作
  • 设计公司logo大概需要多少钱福州网站优化公司
  • 网站模版 模板电大企业网站建设论文范文
  • 网站后台管理系统免费下载wordpress 拖拽神器
  • 杭州 网站程序绵阳市住房和城乡建设局网站
  • 网站wordpress品牌设计logo vi设计
  • 建网站要自己买服务器吗免费制作扫码下单小程序
  • 做实验用哪些国外网站免费自己建网页
  • 网站推广平台湖南网站制作流程
  • 背景 网站建设开发必备软件
  • 网站怎么做实名认证吗建筑工程图纸符号大全图解
  • 美食网站html模板权威发布海报
  • 济南网站建设 推搜点asp网站图片不显示
  • 做化工的 有那些网站做的网站搜不到
  • 哈尔滨网站公司一般做哪些外贸网站
  • 传奇大气网站模板免费下载开发公司总经理竞聘报告
  • 企业网站建设多少钱重庆最新新闻事件火
  • 企业网站建设周期全国商城网站建设
  • 张家港专业的网站制作公司东莞市网络seo推广怎么样
  • 网站建设的法律依据嵊州建设银行取款网站