webpack指南(四)shimming

shimming 将一个新的 API 引入到一个旧的环境中,而且仅靠旧的环境中已有的手段实现。

ProvidePlugin 我们在程序中暴露一个变量,通知webpack某个库被使用,webpack将在最终的bundle中引入该库。

// index.js

function component() {
    var element = document.createElement('div');

    element.innerHTML = _.join(['hello','webpack'],' ');

    return element;

}

document.body.appendChild(component());

注意,这个文件里不需要import _ from lodash了

// webpack.common.js

plugins:[
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title: 'shimming'
        }),
 +       new webpack.ProvidePlugin({
 +          _: 'lodash'
 +       })
    ]

还可以利用ProvidePlugin暴露库中的单一函数(变量)

function component() {
    var element = document.createElement('div');

    element.innerHTML = join(['hello','webpack'],' ');

    return element;

}

document.body.appendChild(component());
    plugins:[
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title: 'shimming'
        }),
        new webpack.ProvidePlugin({
 +           join: ['lodash','join']
        })
    ]

这样,就可以将lodash库中的其他没用到的部分去除。(tree shaking)

注意:任何需要AST的功能,ProvidePlugin都无法正常运行。

 

imports-loader  覆写this指向.

npm i imports-loader

在CommonJS环境下,this指向module.exports。通过imports-loader将this指向window.

function component() {
    var element = document.createElement('div');

    element.innerHTML = join(['hello','webpack'],' ');

+   this.alert('test hahaha');

    return element;

}

document.body.appendChild(component());
module: {
    rules: [
        {
            test: require.resolve('./src/test.js'),
            use: 'imports-loader?this=>window'
        }
    ]
},

 exports-loader  将一个全局变量作为一个普通模块导出。

npm i exports-loader

global.js   // 注意:这个文件中没有任何export语句。

const file = 'this is file text';

var helper = {
    parse: function() {
        console.log('this parse function comes from global.js');
    }
}

webpack.config.js

module: {
        rules: [
           {
                test: require.resolve('./src/global.js'),
                use: 'exports-loader?file,parse=helper.parse'
            }
        ]
    },

运行webpack编译命令,然后在test.js中导入

import {file, parse} from './global';

function component() {
    var element = document.createElement('div');

    element.innerHTML = join(['hello','webpack'],' ');

    console.log(file);
    parse();

    return element;

}

document.body.appendChild(component());

再运行编译命令

 

polyfill 是一个用在浏览器 API 上的 shim。

我们通常的做法是先检查当前浏览器是否支持某个 API,如果不支持的话就加载对应的 polyfill。

npm install --save babel-polyfill
npm install --save whatwg-fetch

官网上,不推荐在主 bundle 中引入 polyfills,因为这不利于已具备这些模块功能的现代浏览器用户,会使他们下载体积很大、但却不需要的脚本文件。推荐做法是将其放入一个单独的文件。

// polyfill.js

import 'babel-polyfill';
import 'whatwg-fetch';
entry: {
     polyfills: './src/polyfills.js',
     index: './src/index.js'
 },

index.html

<!doctype html>
  <html>
    <head>
      <title>Getting Started</title>
+     <script>
        // 检测需要的功能是否支持
+       var modernBrowser = (
+         'fetch' in window &&
+         'assign' in Object
+       );
+      // 若不支持,则导入
+       if ( !modernBrowser ) {
+         var scriptElement = document.createElement('script');
+
+         scriptElement.async = false;
+         scriptElement.src = '/polyfills.bundle.js';
+         document.head.appendChild(scriptElement);
+       }
+     </script>
    </head>
    <body>
      <script src="index.bundle.js"></script>
    </body>
  </html>

script-loader  会在全局上下文中对代码进行取值,类似于通过一个 script 标签引入脚本。在这种模式下,每一个标准的库(library)都应该能正常运行。require,module等取值为undefine.

当使用 script-loader 时,模块将转化为字符串,然后添加到 bundle 中。它不会被webpack 压缩,所以应该选择一个 min 版本。同时,script-loader将不会有devtool 的支持。

这些老旧的模块如果没有 AMD/CommonJS 规范版本,但你也想将他们加入 /dist 目录,你可以使用 noParse 来标识出这个模块。这样就能使 webpack 将引入这些模块,但是不进行转化(parse)和解析(resolve) require和 import 语句。这个实践将提升构建性能。

---------------------------------------------------------------------------------------

在构建中涉及性能的loaders

thread-loader

可以将非常消耗资源的 loaders 转存到 worker pool 中。

cache-loader 启用持久化缓存

可以在多个编译之间共享缓存。

使用 package.json 中的 "postinstall" 清除缓存目录。

 

posted @ 2020-02-04 16:02  cecelia  阅读(408)  评论(0编辑  收藏  举报