浅析webpack之shimming垫片的理解及常见场景和webpack.ProvidePlugin插件的使用

一、shimming 垫片的场景

  在webapck打包的过程中,我们往往需要做代码的兼容,或者打包过程的兼容。比如,我们使用的 @babel/polyfill,他所解决的就是打包代码运行在低版本浏览器上时有些api不兼容的问题,比如IE浏览器上不支持的Promise api,他就会自动的在打包过程中构建这样的兼容低版本的全局变量。这其实就是一种webpack shimming。

  当然了,关于webpack的兼容问题不局限于js语法的高低版本兼容,还有可能是下面这样的一些情况,我们来了解一下。

1、先举一个简单的例子:现在有 2 个 js 文件

//一个index.js,内容如下
import _ from 'lodash';
import $ from 'jquery';
import {ui} from './jquery-ui';
ui();

/*其他业务代码*/

//一个我们模仿的第三方模块jqurey-ui.js文件:
import $ from 'jquery';
export function ui() {
    $('body').css('background', 'red');
}

  两个文件的关系:jqurey-ui.js 是一个第三方模块,jqurey-ui.js 模块依赖于jQuery,但是这个模块中并没有导入jQuery;

  我们在index.js中导入了这个模块,并且在index.js中我们还引入了lodash模块和jquery模块;

  此时,我们去执行导入的UI函数可以运行吗?

  答案是不可以执行,会因为$的未定义而报错。因为在webapck打包中,是以模块来划分的,每一个模块都会引入单独的资源,这样就能保证其资源的独立了。

  因为模块化存在变量隔离的原因,在index.js中导入的jQuery并不能在jquery-ui.js中生效;也就是本模块导入的变量、类、函数,只在本模块生效,不会对导入模块生效;

2、针对上面的情况,我们需要解决导入的模块缺少jQuery依赖的问题,怎么解决?

(1)我们可以手动在第三方模块中导入依赖模块,但是好像不现实。如果是我们自定义的模块还好说,如果是第三方 npm 上的模块呢?因为一般这些模块都是在node_modules中的,我们手动更改第三方模块,可能会导致一些问题。

(2)现在我们已经知道,这个模块缺少jQuery依赖,我们想的是怎么样才能方便安全的把jQuery导入到这个模块中去,那么能否在webpack打包的时候,让webpack帮我们添加哪?

  这个思路貌似可行,webpack也给我们提供了这么一个插件:webpack.ProvidePlugin插件;

二、webpack.ProvidePlugin插件的简单使用

const webpack = require('webpack')
module.exports = {
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery'
    })
  ]
}

  webpack为我们提供了ProvidePlugin的插件,上面配置的意思是,当我们在模块中遇到‘$’就会去自动的引入jquery。这样就实现了一个自动的解决兼容的方法,我们起本地server运行一下。

  有的读者可能心生疑惑了,为什么我们引入的npm可能没有引入 jquery 呢?因为在一些老版本的插件中,没有考虑到未来技术的发展像webpack这样的打包方式,所以是极有可能存在上面说的这样情况的,这也就是为什么我们管这种方式叫shimming的一种情况

  当然了,这个插件的玩法也是比较多,比如我们要对一个lodash方法进行重命名,我们也可以这样做

new webpack.ProvidePlugin({
  _join: ['lodash', 'join']
})
// 后面的数组代表lodash下面的join方法

  总结一下,shimming(垫片)的一个用法:垫片就是通过webpack的ProvidePlugin插件,帮我们在第三方模块中自动的添加该第三方模块需要的或者我们想要的东西

三、使用imports-loader实现垫片

1、首先,一个JS模块中的this指向的模块自身这个前置小知识点,现在我们想让整个模块中的this都指向window,我们不可能一个一个的去改变指向吧?也不能手动去向模块注入吧?最好的办法就是让webpack帮助我们实现;

2、imports-loader的使用:

  安装imports-loader:npm install imports-loader --save-dev;

  配置:

{
  test: /\.js$/,
  exclude: /node_modules/,
  use: [
    { loader: "babel-loader" },
    {
      loader: "imports-loader",
      options: "this=>window"
    }
  ],
 }

  当webpack处理JS文件时,会首先将JS文件交给imports-loader处理,JS模块中的this指向window,然后再交给babel-loader处理

  最后总结一下shimming(垫片):思想就是通过webpack向模块中注入全局性的变量,类,函数等。

posted @ 2017-07-17 23:36  古兰精  阅读(10127)  评论(0编辑  收藏  举报