webpack知识点+面试题

webpack知识点+面试题

1、什么是webpack?

webpack 是代码编译工具,有入口、出口、loader 和插件。webpack 是一个用于现代[ JavaScript ](https://baike.baidu.com/item/ JavaScript /321142)应用程序的静态模块打包工具。当 webpack 处理应用程序时,它会在内部构建一个依赖图(dependency graph),此依赖图对应映射到项目所需的每个模块,并生成一个或多个 bundle

2、谈谈你对webpack的看法

WebPack是一个模块打包工具,你可以使用WebPack管理你的模块依赖,并编绎输出模块们所需的静态文件。它能够很好地管理、打包Web开发中所用到的HTML、Javascript、CSS以及各种静态文件(图片、字体等),让开发过程更加高效。对于不同类型的资源,webpack有对应的模块加载器。webpack模块打包器会分析模块间的依赖关系,最后 生成了优化且合并后的静态资源。

3、webpack的打包体积 优化思路

1、提取第三方库或通过引用外部文件的方式引入第三方库

2、代码压缩插件UglifyJsPlugin

3、服务器启用gzip压缩

4、按需加载资源文件 require.ensure

5、优化devtool中的source-map/6、剥离css文件,单独打包
6、去除不必要插件,通常就是开发环境与生产环境用同一套配置文件导致

4、怎么提高webpack的打包效率?

1、开发环境采用增量构建,启用热更新

2、开发环境不做无意义的工作如提取css计算文件hash等

3、配置devtool

4、选择合适的loader

5、个别loader开启cache 如babel-loader

6、第三方库采用引入方式

7、提取公共代码

8、优化构建时的搜索路径 指明需要构建目录及不需要构建目录

9、模块化引入需要的部分

5、Webpack 的运行(构建)流程是怎样的?

Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:

  1. **初始化参数:**从配置文件 webpack.config.js 和命令行中读取与合并参数,初始化本次构建的配置参数,得出最终的参数;
  2. **开始编译:**用上一步得到的参数初始化 Compiler 对象,加载配置文件的所有 plugin,执行对象的 run 方法开始执行编译;
  3. **确定入口:**根据配置中的 entry 找出所有的入口文件,递归遍历所有的入口文件;
  4. **编译模块:**从入口文件出发,调用所有配置的 loader 对模块进行编译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。
  5. **输出资源:**所有文件的编译及转化都已经完成,也就是最终输出的资源,其中包括即将输出的资源、代码块 Chunk 等等信息。

6、Webpack 的 Loader 是什么?

Webpack 只能理解 JavaScript 和 JSON 文件,这是 Webpack 开箱可用的自带能力。loader 可以让 Webpack 能够去处理其他类型的文件,比如 .scss 和 .ts,并将它们转换为有效的功能离散的 chunk 文件以供应用程序使用,以及被添加到依赖图中,也可将内联图像转换为 data URL。简单来说,loader 可以将一段代码转换成另一端代码,通常用来将一段特殊代码转换成一段浏览器可识别的代码。

loader从下到上地取值(evaluate)/执行(execute),也就是是从后往前执行。在下面的示例中,从 ts-loader开始执行,然后继续执行 css-loader,最后以 raw-loader 为结束。loader 有两个属性:test,正则表达式,用于识别出哪些文件会被转换,use 定义在进行转换时应该使用哪个 loader,可以是字符串、数组和对象。

7、有哪些常见的 Loader ?

raw-loader:加载文件原始内容(utf-8)
file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件 (处理图片和字体)
url-loader:与 file-loader 类似,区别是用户可以设置一个阈值,大于阈值会交给 file-loader 处理,小于阈值时返回文件 base64 形式编码 (处理图片和字体)
source-map-loader:加载额外的 Source Map 文件,以方便断点调试
svg-inline-loader:将压缩后的 SVG 内容注入代码中
image-loader:加载并且压缩图片文件
json-loader 加载 JSON 文件(默认包含)
handlebars-loader: 将 Handlebars 模版编译成函数并返回
babel-loader:把 ES6 转换成 ES5
ts-loader: 将 TypeScript 转换成 JavaScript
awesome-typescript-loader:将 TypeScript 转换成 JavaScript,性能优于 ts-loader
sass-loader:将SCSS/SASS代码转换成CSS
css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS
postcss-loader:扩展 CSS 语法,使用下一代 CSS,可以配合 autoprefixer 插件自动补齐 CSS3 前缀
eslint-loader:通过 ESLint 检查 JavaScript 代码
tslint-loader:通过 TSLint检查 TypeScript 代码
mocha-loader:加载 Mocha 测试用例的代码
coverjs-loader:计算测试的覆盖率
vue-loader:加载 Vue.js 单文件组件
i18n-loader: 国际化
cache-loader: 可以在一些性能开销较大的 Loader 之前添加,目的是将结果缓存到磁盘里

8、Webpack 的 Plugin 是什么?

loader 用于转换某些类型的模块,而 plugin(插件)则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。想要使用一个 plugin,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过 option 自定义,也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建一个插件实例。

9、有哪些常见的 Plugin ?

define-plugin:定义环境变量 (Webpack4 之后指定 mode 会自动配置)
ignore-plugin:忽略部分文件
html-webpack-plugin:简化 HTML 文件创建 (依赖于 html-loader)
web-webpack-plugin:可方便地为单页应用输出 HTML,比 html-webpack-plugin 好用
uglifyjs-webpack-plugin:不支持 ES6 压缩 (Webpack4 以前)
terser-webpack-plugin: 支持压缩 ES6 (Webpack4)
webpack-parallel-uglify-plugin: 多进程执行代码压缩,提升构建速度
mini-css-extract-plugin: 分离样式文件,CSS 提取为独立文件,支持按需加载 (替代extract-text-webpack-plugin)
serviceworker-webpack-plugin:为网页应用增加离线缓存功能
clean-webpack-plugin: 目录清理
ModuleConcatenationPlugin: 开启 Scope Hoisting
speed-measure-webpack-plugin: 可以看到每个 Loader 和 Plugin 执行耗时 (整个打包耗时、每个 Plugin 和 Loader 耗时)
webpack-bundle-analyzer: 可视化 Webpack 输出文件的体积 (业务组件、依赖第三方模块)

10、Webpack 的热更新是什么?

Webpack 的热更新又称热替换(Hot Module Replacement),缩写为 HMR。 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。

11、webpack的热更新原理是怎样的?

1、Webpack 通过 Watch 模式可以侦听文件的变化,当文件发生改变时,会根据配置进行重新编译(Compile),并将编译后的代码保存在内存中。

2、webpack-dev-server 也会对文件变化进行监控(需要配置 devServer.watchContentBase = true),但不会进行重新编译,而是监听这些配置文件中静态文件的变化,变化后会通知浏览器进行直接刷新,而不是 HMR。

3、在浏览器和服务端之间有一个通过 SocketJs 建立的 websocket 长连接。webpack-dev-server 会将 Webpack 编译打包时的各个阶段的状态信息和 hash 值一并告知 webpack-dev-server/client(位于浏览器端)。

4、但是 webpack-dev-server/client 并不能够请求更新的代码,而是把这些工作交给了 webpack/hot/dev-server,webpack/hot/dev-server 的工作就是根据 webpack-dev-server/client 传来的信息以及 dev-server 的配置决定是刷新浏览器还是 HMR。

5、HotModuleReplacement.runtime 是客户端 HMR 的中枢,它接收到 webpack/hot/dev-server 传递的新模块的 hash 值,通过 JsonpMainTemplate.runtime 向 webpack-dev-server 发送 Ajax 请求获取到返回的 Json,该 Json 包含了所有要更新的模块的 hash 值,之后通过 Jsonp 请求,获取到最新的模块代码。

6、接下来,HotModulePlugin 将会对新旧模块进行对比,决定是否更新模块,在决定更新模块后,检查模块之间的依赖关系,更新模块的同时更新模块间的依赖引用。

7、如果 HMR 失败,则通过刷新浏览器来获取最新打包代码。

12、loader 和 plugin 不同?

不同的作用:

Loader直译为"加载器"。Webpack将一切文件视为模块,但是webpack原生是只能解析js文件, 如果想将其他文件也打包的话,就会用到 loader 。 所以Loader的作用是让webpack拥有了加载 和解析非JavaScript文件的能力。

Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。

不同的用法:

Loader在 module.rules 中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项 都是一个 Object ,里面描述了对于什么类型的文件( test ),使用什么加载( loader )和使用的 参数( options )Plugin在 plugins 中单独配置。 类型为数组,每一项是一个 plugin 的实例,参数都通过构造函 数传入。

13 、怎么配置单页应用?怎么配置多页应用?

​ 单页应用可以理解为webpack的标准模式,直接在 entry 中指定单页应用的入口即可,这里不再赘述
​ 多页应用的话,可以使用webpack的 AutoWebPlugin 来完成简单自动化的构建,但是前提是项目的目录结构必须遵守他预设的规范。 多页应用中要注意的是:

​ 每个页面都有公共的代码,可以将这些代码抽离出来,避免重复的加载。比如,每个页面都引用了同一套css样式表

随着业务的不断扩展,页面可能会不断的追加,所以一定要让入口的配置足够灵活,避免每次添加新页面还需要修改构建配置

14、如何用webpack来优化前端性能?

用webpack优化前端性能是指优化webpack的输出结果,让打包的最终结果在浏览器运行快速高效。

1、压缩代码:删除多余的代码、注释、简化代码的写法等等方式。可以利用webpack的 UglifyJsPlugin 和 ParallelUglifyPlugin 来压缩JS文件, 利用 cssnano (css-loader?

minimize)来压缩css

2、利用CDN加速: 在构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用 webpack对于 output 参数和各loader的 publicPath 参数来修改资源路径

3、Tree Shaking: 将代码中永远不会走到的片段删除掉。可以通过在启动webpack时追加参数 – optimize-minimize 来实现

4、Code Splitting: 将代码按路由维度或者组件分块(chunk),这样做到按需加载,同时可以充分利用浏览

器缓存

5、提取公共第三方库: SplitChunksPlugin插件来进行公共模块抽取,利用浏览器缓存可以长期缓存这 些无需频繁变动的公共代码

15、 分别介绍bundle,chunk,module是什么

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

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

module:是开发中的单个模块,在webpack的世界,一切皆模块,一个模块对应一个文件, webpack会从配置的entry中递归开始找出所有依赖的模块

16、webpack,rollup,parcel优劣?

webpack适用于大型复杂的前端站点构建: webpack有强大的loader和插件生态,打包后的文件实际上就是一个立即执行函数,这个立即执行函数接收一个参数,这个参数是模块对象,键为各个模块的路径,值为模块内容。立即执行函数内部则处理模块之间的引用,执行模块等,这种情况更适合文件依赖复杂的应用开发.

rollup适用于基础库的打包,如vue、d3等: Rollup 就是将各个模块打包进一个文件中,并且通过 Tree-shaking 来删除无用的代码,可以最大程度上降低代码体积,但是rollup没有webpack如此多的的如代码分割、按需加载等高级功能,其更聚焦于库的打包,因此更适合库的开发.

parcel适用于简单的实验性项目: 他可以满足低门槛的快速看到效果,但是生态差、报错信息不够全面都是他的硬伤,除了一些玩具项目或者实验项目不建议使用

17、Webpack的基本功能有哪些?

代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等

文件优化:压缩JavaScript、CSS、html 代码,压缩合并图片等

代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载

模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件

自动刷新:监听本地源代码的变化,自动构建,刷新浏览器代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过

自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统

18、webpack.config.js能不能重命名?

可以 在package.json中

19、webpack.config.js能不能做拆分?

可以

将webpack.config.js 配置文件进行分开。分成三个配置文件,如下:

  1. webpack.base.config.js:两个环境公共的部分
  2. webpack.dev.config.js:开发环境独有的配置
  3. webpack.prod.config.js`:生产环境独有的配置

20、entry的值有几种数据类型?

字符串(单入口)

数组(多入口)

object(object中的key在webpack里相当于此入口的name)

21、output的对像中的常见属性有哪些?

-path(path参数表示生成文件的根目录,需要传入一个绝对路径。

path参数和后面的filename参数共同组成入口文件的完整路径。),

-publicPath(表示的是一个URL路径(指向生成文件的根目录,静态资源),用于生成css/js/图片/字体文件等资源的路径,以确保网页能正确地加载到这些资源。

22、publicPath参数跟path参数的区别是:path参数其实是针对本地文件系统的,而publicPath则针对的是浏览器)

-filePath(表示的是如何命名生成出来的入口文件),

-chunkFilename(chunkFilename参数与filename参数类似,都是用来定义生成文件的命名方式的,只不过,chunkFilename参数指定的是除入口文件外的chunk(这些chunk通常是由于webpack对代码的优化所形成的,比如因应实际运行的情况来异步加载)的命名)

23、什么是Tree-sharking?

指打包中去除那些引入了但在代码中没用到的死代码。在wepack中js treeshaking通过UglifyJsPlugin来进行,css中通过purify-CSS来进行。

24、webpack-dev-server 和 http服务器的区别

webpack-dev-server使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,比传统的http服务对开发更加有效。

25、webpack3和webpack4的区别

mode/–mode参数,新增了mode/–mode参数来表示是开发还是生产(development/production)production 侧重于打包后的文件大小,development侧重于goujiansud移除loaders,必须使用rules(在3版本的时候loaders和rules 是共存的但是到4的时候只允许使用rules)移除了CommonsChunkPlugin (提取公共代码),用optimization.splitChunks和optimization.runtimeChunk来代替支持es6的方式导入JSON文件,并且可以过滤无用的代码

26、如何编写一个 plugins

// 新建一个plugins目录
// 目录下新建一个copyright-webpack-plugin.js文件
class CopyrightWebpackPlugin {
  apply(compiler) {
    compiler.hooks.compile.tap('CopyrightWebpackPlugin',
      (compilation) => {
        console.log('compiler');
      }
    )
    compiler.hooks.emit.tapAsync('CopyrightWebpackPlugin',
      (compilation, cb) => {
        debugger;
        compilation.assets['copyright.txt'] = {
          source: function () {
            return 'copyright by black uncle'
          },
          size: function () {
            return 24;
          }
        };
        cb();
      }
    )
  }
}
module.exports = CopyrightWebpackPlugin;

// webpack.config.js的配置文件
const path = require('path');
const CopyRightWebpackPlugin = require('./plugins/copyright-webpack-plugin');

module.exports = {
  mode: 'development',
  entry: {
    main: './src/index.js'
  },
  plugins: [
    new CopyRightWebpackPlugin()
  ],
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  }
}

27、如何编写一个 Loader

// 如何编写一个 Loader
// 新建一个loaders目录
// 目录下新建一个replaceLoader.js文件
const loaderUtils = require('loader-utils');
module.exports = function (source) {
  return source.replace('blue', 'black');
}
目录下新建一个replaceLoaderAsync.js文件
const loaderUtils = require('loader-utils');
module.exports = function (source) {
  const options = loaderUtils.getOptions(this);
  const callback = this.async();
  setTimeout(() => {
    const result = source.replace('dalao', options.name);
    callback(null, result);
  }, 1000);
}

// webpack.config.js的配置文件
const path = require('path');
module.exports = {
  mode: 'development',
  entry: {
    main: './src/index.js'
  },
  resolveLoader: {
    modules: ['node_modules', './loaders']
  },
  module: {
    rules: [{
      test: /\.js/,
      use: [
        // {
        //  loader: 'replaceLoader',
        // },
        // {
        //  loader: 'replaceLoaderAsync',
        //  options: {
        //      name: 'uncle'
        //  }
        // },
        {
          loader: path.resolve(
            __dirname,
            './loaders/replaceLoader.js'
          )
        },
        {
          loader: path.resolve(
            __dirname,
            './loaders/replaceLoaderAsync.js'
          ),
          options: {
            name: 'uncle'
          }
        }
      ]
    }]
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  }
}

28、按需加载的原理

定义installedChunks对象,存储异步js的promise回调,如果已经加载过,则返回一个空数组的promise.all([]),如果在加载过程中,则返回已经存储过的此文件对应的promi

29、webpack有什么优势?

(1) webpack 是以 commonJS 的形式来书写脚本滴,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。

(2)能被模块化的不仅仅是 JS 了。

(3) 开发便捷,能替代部分 grunt/gulp 的工作,比如打包、压缩混淆、图片转base64等。

(4)扩展性强,插件机制完善

30、什么是长缓存?在webpack中如何做到长缓存优化?

浏览器在用户访问页面的时候,为了加快加载速度,会对用户访问的静态资源进行存储,但是每一次代码升级或者更新,都需要浏览器去下载新的代码,最方便和最简单的更新方式就是引入新的文件名称。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值