模块化面试题

模块化面试题


文章目录



前言


一、前端模块化问题

1.1 你对前端模块化的理解?

1.1.1 模块化

1、将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起

2、块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信


1.1.2 模块化开发的好处 方便代码的重用,从而提升开发效率,并且方便后期的维护


1.1.3 浏览器端模块化规范

1、 AMD 异步加载模块

(1) 定义暴露模块
//定义没有依赖的模块
define(function(){
   return 模块
})

//定义有依赖的模块
define(['module1', 'module2'], function(m1, m2){
   return 模块
})
(2)引入使用模块
require(['module1', 'module2'], function(m1, m2){
   使用m1/m2
})

2、 CMD 结合了AMD和CommonJS,实现者是Sea.js

(1) 下载sea.js, 并引入

http://seajs.org/

(2) 创建项目结构
|-js
  |-libs
    |-sea.js
  |-modules
    |-module1.js
    |-module2.js
    |-module3.js
    |-module4.js
    |-main.js
|-index.html
(3) 定义sea.js的模块代码
// module1.js文件
define(function (require, exports, module) {
  //内部变量数据
  var data = 'atguigu.com'
  //内部函数
  function show() {
    console.log('module1 show() ' + data)
  }
  //向外暴露
  exports.show = show
})


// module2.js文件
define(function (require, exports, module) {
  module.exports = {
    msg: 'I Will Back'
  }
})


// module3.js文件
define(function(require, exports, module) {
  const API_KEY = 'abc123'
  exports.API_KEY = API_KEY
})


// module4.js文件
define(function (require, exports, module) {
  //引入依赖模块(同步)
  var module2 = require('./module2')
  function show() {
    console.log('module4 show() ' + module2.msg)
  }
  exports.show = show
  //引入依赖模块(异步)
  require.async('./module3', function (m3) {
    console.log('异步引入依赖模块3  ' + m3.API_KEY)
  })
})


// main.js文件
define(function (require) {
  var m1 = require('./module1')
  var m4 = require('./module4')
  m1.show()
  m4.show()
})

1.1.4 服务器端模块化规范

1、 CommonJS

(1)require读入并执行一个JavaScript文件,然后返回该模块的exports对象。
(2) 输入返回值同函数,只是值的拷贝
// example.js
var x = 5;
var addX = function (value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;
var example = require('./example.js');//如果参数字符串以“./”开头,则表示加载的是一个位于相对路径
console.log(example.x); // 5
console.log(example.addX(1)); // 6

1.1.5 ES6模块化规范

1、浏览器端与服务器端通用的模块化开发规范`

2、 每个 js 文件都是一个独立的模块

3、 导入模块成员使用 import 关键字

4、 暴露模块成员使用 export 关键字

/*-------------默认导出与默认导入-------------*/

// export-default.js    默认导出 export default{....}
function sum(num1, num2) {
    return num1 + num2
}
export default {name:'jack', height: 170, age:23, sum}

// import-default.js    默认导入 import 接收名称 from '模块标识符'`
import obj from './export-default';
console.log(obj); // {name:'jack', height: 170, age:23, sum}
/*-------------按需导出与按需导入-------------*/
// 按需导出
export var a = 10
export function xx(){} 

// 按需导入
import {变量,方法,类} from  模块文件名字
import {xx as 别名,xx,xx} from  模块文件名字


二、 webpack问题

2.1 webpack是什么?

2.1.1 webpack 是个静态模块打包工具。 在webpack中,项目里所有资源皆模块,利用资源依赖关系把各模块之间关联起来。

2.1.2 webpack 通过 入口文件 开始,利用递归找到直接依赖或间接依赖的所有模块,并在内部构建一个能映射出项目所需的所有模块的依赖图,并进行webpack打包生成一个或多个bundle文件


2.2 webpack的loader和plugin分别是什么?

2.2.1 loader 模块转换器。

1、webpack 将一切文件视为模块,但webpack默认只能打包处理JavaScript 文件

2、loader 作用是让 webpack 拥有了加载和解析非 JavaScript 文件的能力。


2.2.2 plugin在 webpack 构建流程中的特定时机注入扩展逻辑,让它具有更多的灵活性。

1、在 webpack 运行的生命周期中会广播出许多事件

2、plugin 可以监听这些事件,在合适的时机通过 webpack 提供的 API 改变输出结果。

在这里插入图片描述


2.3 常用的loader和plugin有哪些?

2.3.1 常用的loader

1、styler-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。

2、css-loader:加载 CSS,支持模块化、压缩、文件导入等特性

3、sass-loader

4、postcss-loader 补全 css 兼容前缀

5、babel-loader:将ES6转为ES5

6、vue-loader


2.3.2 常用的plugin

1、clean-webpack-plugin : 删除打包文件

2、html-webpack-plugin:简化 HTML 文件创建 (依赖于 html-loader)

3、CompressionWebpackPlugin:打包时开启gzip压缩

4、SplitChunksPlugin:提取公共代码,分割代码

5、HotModuleReplacementPlugin:热替换模块

6、happypack:实现多线程加速编译



2.4 bundle,chunk,module 是什么?

2.4.1 bundle 是由 webpack 打包出来的文件

2.4.2 chunk 代码块,一个 chunk 由多个模块组合而成,用于代码的合并和分割。

2.4.3 module 是开发中的单个模块,一个模块对应一个文件,webpack 会从配置的entry中递归开始找出所有依赖的模块。


2.5 webpack 的热更新原理是什么?

2.5.1 热更新又称热替换(Hot Module Replacement),缩写为 HMR,基于 webpack-dev-server。

2.5.2 浏览器的网页通过websocket协议与服务器建立起一个长连接,并监听本地文件的改动;

2.5.3 当服务器的css/js/html进行了修改的时候,服务器会向前端发送一个更新的消息,如果是css或者html发生了改变,网页执行js直接操作dom,局部刷新,如果是js发生了改变,只能刷新整个页面。


2.6 请说说webpack 的构建流程?

2.6.1 初始化参数 从配置文件 和 Shell 语句中读取与合并参数,得出最终的参数

2.6.2 开始编译 用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;

2.6.3 确定入口 根据配置中的 entry 找出所有的入口文件;

2.6.4 编译模块 从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;

2.6.5 完成模块编译 在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;

2.6.6 输出资源 根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;

2.6.7 输出完成 在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。在以上过程中,webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用webpack 提供的 API 改变 webpack 的运行结果。




总结

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐