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

网页设计做军事网站的感想平面设计和网站运营

网页设计做军事网站的感想,平面设计和网站运营,seo怎么读,一般纳税人企业所得税webpack打包的基本原理 核心功能就是把我们写的模块化代码转换成浏览器能够识别运行的代码,话不多说我们一起来了解它 首先我们建一个空项目用 npm init -y 创建一个初始化的,在跟目录下创建src文件夹,src下创建index.js,add.js…

webpack打包的基本原理

核心功能就是把我们写的模块化代码转换成浏览器能够识别运行的代码,话不多说我们一起来了解它

首先我们建一个空项目用 npm init -y 创建一个初始化的,在跟目录下创建src文件夹,src下创建index.js,add.js,square.js,tip.js。在根目录下创建index.html
在这里插入图片描述
index.html引入index.js,index.js引入add.js、square.js。square.js引入tip.js

//add.js
export default (a, b) => {return a + b;
};//square.js
import tip from "tip.js";
const square = (a) => {console.log(tip);return a * a;
};
export { square };//tip.js
export default "我是提示-----";

index.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body></body><script src="./src/index.js"></script>
</html>

运行index.html会报错,不能识别es6的模块化导入
在这里插入图片描述
让我们来实现webpack打包的核心功能

实现webpack打包核心功能

首先在根目录下建一个bundle.js用来对刚刚写的index.js进行打包
webpack官网对打包流程的介绍

it internally builds a dependency graph which maps every module your project needs and generates one or more bundles(webpack会在内部构建一个 依赖图(dependency graph),此依赖图会映射项目所需的每个模块,并生成一个或多个 bundle)

根据上面的说明进行分析,打包的工作基本流程如下

  1. 读取入口文件中的内容(也就是index.js文件)
  2. 分析入口文件,递归读取模块所依赖的文件 内容,生成依赖图
  3. 根据依赖图生成浏览器能运行的代码

1、处理单个模块内容

const fs = require("fs");
const getModuleInfo = (file) => {const body = fs.readFileSync(file, "utf-8");//获取文件内容,是字符串console.log(body);
};
getModuleInfo("./src/index.js");

打印出来是文件内容的字符串
在这里插入图片描述
借助安装@babel/parser 把,js文件代码转换成js对象,叫做抽象语法树(ast)

const fs = require("fs");
const parser = require("@babel/parser");
const getModuleInfo = (file) => {const body = fs.readFileSync(file, "utf-8");const ast = parser.parse(body, {//表示我们要解析的是es6模块sourceType: "module",});console.log(ast.program.body);
};
getModuleInfo("./src/index.js");

打印ast.program.body的结构:

[Node {type: 'ImportDeclaration', start: 0,end: 27,loc: SourceLocation {      start: [Position],       end: [Position],filename: undefined,     identifierName: undefined},specifiers: [ [Node] ],source: Node {type: 'StringLiteral',start: 16,end: 26,loc: [SourceLocation],extra: [Object],value: './add.js'}},Node {type: 'ImportDeclaration',start: 29,end: 66,loc: SourceLocation {start: [Position],end: [Position],filename: undefined,identifierName: undefined},specifiers: [ [Node] ],source: Node {type: 'StringLiteral',start: 52,end: 65,loc: [SourceLocation],extra: [Object],value: './square.js'}},Node {type: 'VariableDeclaration',start: 68,end: 90,loc: SourceLocation {start: [Position],end: [Position],filename: undefined,identifierName: undefined},declarations: [ [Node] ],kind: 'const'},Node {type: 'VariableDeclaration',start: 92,end: 114,loc: SourceLocation {start: [Position],end: [Position],filename: undefined,identifierName: undefined},declarations: [ [Node] ],kind: 'const'},Node {type: 'ExpressionStatement',start: 116,end: 143,loc: SourceLocation {start: [Position],end: [Position],filename: undefined,identifierName: undefined},expression: Node {type: 'CallExpression',start: 116,end: 142,loc: [SourceLocation],callee: [Node],arguments: [Array]}},Node {type: 'ExpressionStatement',start: 145,end: 172,loc: SourceLocation {start: [Position],end: [Position],filename: undefined,identifierName: undefined},expression: Node {type: 'CallExpression',start: 145,end: 171,loc: [SourceLocation],callee: [Node],arguments: [Array]}}
]

type属性是ImportDeclaration的节点,其source.value属性是引入这个模块的相对路径,上面打印出两个ImportDeclaration节点,说明对应的是入口文件中的两个import

对ast.program.body做处理,本质上是对这个数组遍历,循环做处理,借助安装@babel/traverse来完成这项工作

const fs = require("fs");
const path = require("path");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;const getModuleInfo = (file) => {//1、把入口文件字符串ast对象const body = fs.readFileSync(file, "utf-8");const ast = parser.parse(body, {//表示我们要解析的是es6模块sourceType: "module",});//2、获取类型为ImportDeclaration的所依赖模块的信息地址const deps = {};//创建一个对象deps,用来收集模块自身引入的依赖,用traverse遍历需要的ImportDeclaration节点做处理,把相对路径转成绝对路径traverse(ast, {ImportDeclaration({ node }) {const dirname = path.dirname(file);let absPath = "./" + path.join(dirname, node.source.value);absPath = absPath.replace("\\", "/");deps[node.source.value] = absPath;},});console.log(deps);
};
getModuleInfo("./src/index.js");

deps打印出入口文件引入的依赖地址
在这里插入图片描述
获取依赖后,需要对ast做语法转换,把es6转成es5的语法,安装@babel/core以及@babel/preset-env完成

const fs = require("fs");
const path = require("path");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const babel = require("@babel/core");const getModuleInfo = (file) => {//1、把入口文件字符串ast对象const body = fs.readFileSync(file, "utf-8");const ast = parser.parse(body, {//表示我们要解析的是es6模块sourceType: "module",});//2、获取类型为ImportDeclaration的所依赖模块的信息地址const deps = {};//创建一个对象deps,用来收集模块自身引入的依赖,用traverse遍历需要的ImportDeclaration节点做处理,把相对路径转成绝对路径traverse(ast, {ImportDeclaration({ node }) {const dirname = path.dirname(file);let absPath = "./" + path.join(dirname, node.source.value);absPath = absPath.replace("\\", "/");deps[node.source.value] = absPath;},});//3、把es6语法转换成es5const { code } = babel.transformFromAst(ast, null, {presets: ["@babel/preset-env"],});const moduleInfo = { file, deps, code };console.log(moduleInfo);return moduleInfo;
};
getModuleInfo("./src/index.js");

moduleInfo 打印结果为:
在这里插入图片描述
最终把一个模块的代码转化为一个对象形式的信息,这个对象包含文件的绝对路径,文件所依赖模块的信息,以及模块内部经过babel转化后的代码

接下去需要递归查找所有的模块,比如square.js里引用了tip.js。
这个过程也是获取依赖图(dependency graph)的过程

const fs = require("fs");
const path = require("path");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const babel = require("@babel/core");const getModuleInfo = (file) => {//1、把入口文件字符串ast对象const body = fs.readFileSync(file, "utf-8");const ast = parser.parse(body, {//表示我们要解析的是es6模块sourceType: "module",});//2、获取类型为ImportDeclaration的所依赖模块的信息地址const deps = {};//创建一个对象deps,用来收集模块自身引入的依赖,用traverse遍历需要的ImportDeclaration节点做处理,把相对路径转成绝对路径traverse(ast, {ImportDeclaration({ node }) {const dirname = path.dirname(file);let absPath = "./" + path.join(dirname, node.source.value);absPath = absPath.replace("\\", "/");deps[node.source.value] = absPath;},});//3、把es6语法转换成es5const { code } = babel.transformFromAst(ast, null, {presets: ["@babel/preset-env"],});const moduleInfo = { file, deps, code };return moduleInfo;
};//4、递归获取所有模块信息和之间的依赖关系
const parseModules = (file) => {//定义依赖图const depsGraph = {};// 首先获取入口的信息const entry = getModuleInfo(file);const temp = [entry];for (let i = 0; i < temp.length; i++) {const item = temp[i];const deps = item.deps;if (deps) {//遍历模块的依赖,递归获取模块信息for (const key in deps) {if (deps.hasOwnProperty(key)) {temp.push(getModuleInfo(deps[key]));}}}}temp.forEach((moduleInfo) => {depsGraph[moduleInfo.file] = {deps: moduleInfo.deps,code: moduleInfo.code,};});console.log(depsGraph);return depsGraph;
};
parseModules("./src/index.js");

获得的depsGraph对象如下:

{file: './src/index.js',deps: { './add.js': './src/add.js', './square.js': './src/square.js' },code: '"use strict";\n' +'\n' +'var _add = _interopRequireDefault(require("./add.js"));\n' +'var _square = require("./square.js");\n' +'function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }\n' +'var sum = (0, _add["default"])(2, 3);\n' +'var sqr = (0, _square.square)(4);\n' +'console.log("sum===", sum);\n' +'console.log("sqr===", sqr);'
}
PS C:\Users\keyuan04\Desktop\webpack> node bundle.js
{'./src/index.js': {deps: { './add.js': './src/add.js', './square.js': './src/square.js' },code: '"use strict";\n' +'\n' +'var _add = _interopRequireDefault(require("./add.js"));\n' +'var _square = require("./square.js");\n' +'function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }\n' +'var sum = (0, _add["default"])(2, 3);\n' +'var sqr = (0, _square.square)(4);\n' +'console.log("sum===", sum);\n' +'console.log("sqr===", sqr);'},'./src/add.js': {deps: {},code: '"use strict";\n' +'\n' +'Object.defineProperty(exports, "__esModule", {\n' +'  value: true\n' +'});\n' +'exports["default"] = void 0;\n' +'var _default = function _default(a, b) {\n' +'  return a + b;\n' +'};\n' +'exports["default"] = _default;'},'./src/square.js': {deps: { 'tip.js': './src/tip.js' },code: '"use strict";\n' +'\n' +'Object.defineProperty(exports, "__esModule", {\n' +'  value: true\n' +'});\n' +'exports.square = void 0;\n' +'var _tip = _interopRequireDefault(require("tip.js"));\n' +'function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }\n' +'var square = function square(a) {\n' +'  console.log(_tip["default"]);\n' +'  return a * a;\n' +'};\n' +'exports.square = square;'},'./src/tip.js': {deps: {},code: '"use strict";\n' +'\n' +'Object.defineProperty(exports, "__esModule", {\n' +'  value: true\n' +'});\n' +'exports["default"] = void 0;\n' +'var _default = "我是提示-----";\n' +'exports["default"] = _default;'}
}

我们最终得到的模块分析数据如上图所示,接下来,我们就要根据这里获得的模块分析数据,来生产最终浏览器运行的代码。

上面打印的依赖图可以看到,最终的code里包含exports以及require这样的语法,所以,我们在生成最终代码时,要对exports和require做一定的实现和处理,把依赖图对象中的内容转换成能够执行的代码,以字符串形式输出。 我们把整个代码放在自执行函数中,参数是依赖图对象
把取得入口文件 的code信息,去执行。使用eval函数执行。
最后把生成的内容写入到dist文件中

const fs = require("fs");
const path = require("path");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const babel = require("@babel/core");const getModuleInfo = (file) => {//1、把入口文件字符串ast对象const body = fs.readFileSync(file, "utf-8");const ast = parser.parse(body, {//表示我们要解析的是es6模块sourceType: "module",});//2、获取类型为ImportDeclaration的所依赖模块的信息地址const deps = {};//创建一个对象deps,用来收集模块自身引入的依赖,用traverse遍历需要的ImportDeclaration节点做处理,把相对路径转成绝对路径traverse(ast, {ImportDeclaration({ node }) {const dirname = path.dirname(file);let absPath = "./" + path.join(dirname, node.source.value);absPath = absPath.replace("\\", "/");deps[node.source.value] = absPath;},});//3、把es6语法转换成es5const { code } = babel.transformFromAst(ast, null, {presets: ["@babel/preset-env"],});const moduleInfo = { file, deps, code };return moduleInfo;
};//4、递归获取所有模块信息和之间的依赖关系
const parseModules = (file) => {//定义依赖图const depsGraph = {};// 首先获取入口的信息const entry = getModuleInfo(file);const temp = [entry];for (let i = 0; i < temp.length; i++) {const item = temp[i];const deps = item.deps;if (deps) {//遍历模块的依赖,递归获取模块信息for (const key in deps) {if (deps.hasOwnProperty(key)) {temp.push(getModuleInfo(deps[key]));}}}}temp.forEach((moduleInfo) => {depsGraph[moduleInfo.file] = {deps: moduleInfo.deps,code: moduleInfo.code,};});console.log(depsGraph);return depsGraph;
};//生成最终代码
const bundle = (file) => {//把依赖图转字符串,放在自执行函数中执行const depsGraph = JSON.stringify(parseModules(file));return `(function(graph){function require(file){var exports = {};function absRequire(relPath){return require(graph[file].deps[relPath])}(function(require,exports,code){eval(code)})(absRequire,exports,graph[file].code)return exports}require('${file}')})(${depsGraph})`;
};const content = bundle("./src/index.js");
fs.rmdirSync("./dist", { recursive: true });
// 写入到dist/bundle.js
fs.mkdirSync("./dist");
fs.writeFileSync("./dist/build.js", content);

最后在index.html中入这个./dist/bundle.js,在控制台就可以看到正确的输出结果
在这里插入图片描述

http://www.yayakq.cn/news/13601/

相关文章:

  • 网站建设的基本情况湖南学校网站建设
  • h5网站设计报价学网站开发与维护有用吗
  • 网站首页鲁大师温州哪里有做网站
  • 网站制作一般收费做电子网站
  • 丰台网站建设公司网络工程师考试资料
  • 网站页面设计 颜色 背景 要求WordPress大气模板
  • 网站权重多少4python 安装wordpress
  • 淘宝网站建设违规吗网站建设栏目设计
  • 网站开发可以当程序员备案的网站 ,能拿来做仿站吗
  • 新手做网站设计莱芜网页定制
  • 网站怎么做留言板网站开发与实训报告
  • ui设计师网站淘宝客手机网站怎么做
  • 网站的按钮怎么做德州北京网站建设
  • 网站每天更新的内容是内链吗网站开发后台的问题
  • 网站建设计入什么会计科目皮包设计制作培训
  • 衡阳市住建局官方网站南充网站建设网站
  • 专做袜子的网站网站服务费做啥费用
  • 建站平台 在线提交表格做电影收费网站
  • 临沂龙文网站建设城乡住房和城乡建设网站查询
  • 做视频网站多大空间够如何制作一个网站包含多个网页
  • 用asp.net做的购物网站建材企业网站源码
  • 江苏城乡建设职业学院就业网站网站服务器建立
  • 什么软件制作图片百度seo正规优化
  • 怎么做家具网站常德网站开发服务
  • 网站域名可以自己做吗阳江网站建设推广
  • 网站建设公司注册沧州网络公司电话
  • 哪些网站适合用自适应通过网站如何做海外贸易
  • 齐河专业企业网站建设在网站上做招聘版面
  • 如果在工商局网站上做股权质押建设领域信用系统网站
  • 企业网站模板建站费用长沙seo结算