webpack主要内容

webpack的核心概念:
·    entry 一个可执行模块或库的入口文件。
·    chunk 多个文件组成的一个代码块,例如把一个可执行模块和它所有依赖的模块组合和一个 chunk 这体现了webpack的打包机制。
·    loader 文件转换器,例如把es6转换为es5,scss转换为css。
·    plugin 插件,用于扩展webpack的功能,在webpack构建生命周期的节点上加入扩展hook为webpack加入功能。
从启动webpack构建到输出结果经历了一系列过程,它们是:
1.    解析webpack配置参数,合并从shell传入和webpack.config.js文件里配置的参数,生产最后的配置结果。
2.    注册所有配置的插件,好让插件监听webpack构建生命周期的事件节点,以做出对应的反应。
3.    从配置的entry入口文件开始解析文件构建AST语法树,找出每个文件所依赖的文件,递归下去。
4.    在解析文件递归的过程中根据文件类型和loader配置找出合适的loader用来对文件进行转换。
5.    递归完后得到每个文件的最终结果,根据entry配置生成代码块chunk。
6.    输出所有chunk到文件系统。
需要注意的是,在构建生命周期中有一系列插件在合适的时机做了合适的事情,比如UglifyJsPlugin会在loader转换递归完后对结果再使用UglifyJs压缩覆盖之前的结果。
 
 
webpack是react项目标配的打包工具,和NPM搭配起来使用管理模块实在非常方便。
  webapck 把所有的静态资源都看做是一个 module,通过 webpack,将这些 module 组成到一个 bundle 中去,从而实现在页面上引入一个 bundle.js,来实现所有静态资源的加载。
 
 
webpack 打包后源码有读过吗 模块之间怎么依赖的
每个模块都会被赋予一个id(正常是从0开始的数字),模块之间通过内置的__webpack_require__函数来模拟CommonJS,从而建立联系
 
webpack打包流程
流程图:  https://img.alicdn.com/tps/TB1GVGFNXXXXXaTapXXXXXXXXXX-4436-4244.jpg
 
webpack中的ESlint怎么配置
1).安装
需要这几个npm包:
·    eslint
·    eslint-loader
·    eslint-plugin-html (用以lint一些在html文件里面通过script包裹的js代码,它默认的匹配规则是不带type属性,或者是`/^(application|text)/(x-)?(javascript|babel|ecmascript-6)$/i`,具体的内容请查阅相关文档,通过cli启动lint的时候定义文件后缀名时eslint --ext .html,.js)
·    eslint-config-standard (和javascript-style-standard风格指南需要的包)
·    eslint-plugin-promise
·    eslint-plugin-standard
·    eslint-friendly-formatter (生成的报告格式)
2).配置ESlint
关于eslint的配置方式。比较多元化:
·    js注释
·    .eslintrc.*文件
·    package.json里面配置eslintConfig字段
可以使用任何一个配置来配置ESlint,对于ESlint如何配置,这个里就不赘述了.
3).配置webpack
在webpack中的js模块处进行eslint-loader的配置,示例代码如下所示:
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/, // exclude: /node_modules/ 可以不用定义这个字段的属性值,eslint会自动忽略node_modules
enforce: 'pre', // 在babel-loader对源码进行编译前进行lint的检查
include: /src/, // src文件夹下的文件需要被lint
use: [{
loader:'babel-loader'
},{
loader: 'eslint-loader',
options: {
formatter: require('eslint-friendly-formatter') // 编译后错误报告格式
}
}],
query: {
cacheDirectory: true
}
}
]
}
4).配置package.json
在package.json中配置npm命令:
{
        ...
        "lint": "eslint --ext .js src"
        ...
}
然后执行npm run lint 来进行代码的静态检查
 
 

定位 Webpack 速度慢的原因

打包的命令webpack后加三个参数:
  • --colors 输出结果带彩色,比如:会用红色显示耗时较长的步骤
  • --profile 输出性能数据,可以看到每一步的耗时
  • --display-modules 默认情况下 node_modules 下的模块会被隐藏,加上这个参数可以显示这些被隐藏的模块
从命令行的结果里具体分析速度慢的原因。
 
 

通过Resolve设置,提高模块分析依赖的速度

resolve主要是用来配置解析模块路径和分析依赖,可以让require模块的定位更快。
1.resolve.alias
别名是 Webpack 的一个配置项,它的作用是把用户的一个请求重定向到另一个路径 。如果在alias中定义了值,然后在代码中require该值的时候,会重定向到alias指定的位置。
 
2.resolve.root和resolve.modulesDirectories
root是通过绝对路径的方式来定义查找模块的文件夹。可以是一个数组,主要是用来增加模块的搜寻位置使用的。
modulesDirectories是用来设置搜索的目录名的,默认值:["web_modules", "node_modules"]。如果把值设置成["mydir"]
, webpack会查询 “./mydir”, “../mydir”, “../../mydir”等。
注意: Passing"../someDir","app","."or an absolute path isn’t necessary here. Just use a directory name, not a path. Use only if you expect to have a hierarchy within these folders. Otherwise you may want to use theresolve.root
option instead.
 

配置module.noParse

module.noParse是webpack的另一个很有用的配置项,如果你 确定一个模块中没有其它新的依赖就可以配置这项,webpack将不再扫描这个文件中的依赖。
module: {
    noParse: [/moment-with-locales/]
}
 

配置Loader的exclude或include来设定babel的使用范围

对于很多的 npm 包来说,他们完全没有经过 babel 的必要(成熟的 npm 包会在发布前将自己 es5,甚至 es3 化),让这些包通过 babel 会带来巨大的性能负担。
使用 exclude,屏蔽掉 npm 里的包,从而使整包的构建效率飞速提高。
module: {
   loaders: [ {
     test: /\.js(x)*$/,
     loader: 'babel-loader',
     exclude: function(path) {
         // 路径中含有 node_modules 的就不去解析。
         var isNpmModule = !!path.match(node_modules/);
         return isNpmModule;
    },
    query: {
        presets: ['react', 'es2015-ie', 'stage-1']
    }
  } ]
}
甚至,在十分确信的情况下,使用 include 来限定 babel 的使用范围,进一步提高效率。
module: {
    loaders: [ {
       test: /\.js(x)*$/,
       loader: 'babel-loader',
       include: [  
          // 只去解析运行目录下的 src 和 demo 文件夹
          path.join(process.cwd(), './src'),
          path.join(process.cwd(), './demo')
       ],
       query: {
           presets: ['react', 'es2015-ie', 'stage-1']
       }
    } ]
}
 

使用externals,把不需要打包的模块排除在外

Webpack 可以配置 externals来将依赖的库指向全局变量,从而不再打包这个库。在页面上引入 Web 上的公用 CDN 服务。
webpack中配置:
     externals: { moment: true }
 
页面html上引入script:
<script src="//apps.bdimg.com/libs/moment/2.8.3/moment-with-locales.min.js"></script>
等于让 Webpack 知道,对于 moment这个模块就不要打包啦,直接指向 window.moment就好。不过别忘了加载moment-with-locales.min.js,让全局中有 moment这个变量。
 

使用DLL & DllReference

除了正在开发的源代码之外,通常还会引入很多第三方 NPM 包,这些包我们不会进行修改,但是仍然需要在每次 build 的过程中消耗构建性能,那有没有什么办法可以减少这些消耗呢?DLLPlugin 就是一个解决方案,他通过前置这些依赖包的构建,来提高真正的 build 和 rebuild 的构建效率。
首先,我们来写一个 DLLPlugin 的 config 文件。定义webpack-dll-config.js文件:
const path = require('path');
const webpack=require('webpack');
 
const vendors=[
    'react',
    'react-dom',
    'react-router',
    'history',
    'immutable',
    'redux',
    'react-redux',
    'redux-router',
    'redux-thunk',
    'moment',
    'es6-promise',
    'whatwg-fetch',
    'lodash'
];
 
module.exports={
    entry:{
        'vendor':vendors,
    },
    output:{
        path:path.join(__dirname, 'dist'),
        filename:'[name].dll.js',//[name]的部分由entry的名字替换
        /**
         * output.library
         * 将会定义为 window.${output.library}
         * 在这次的例子中,将会定义为`window.vendor_library`
         */
        library:'[name]_library',
    },
    plugins:[
        new webpack.DllPlugin({
            /**
             * path 定义 manifest 文件生成的位置
             */
            path:'manifest.json',
            /**
             * name 是dll暴露的对象名,要跟 output.library 保持一致;
             * dll bundle 输出到那个全局变量上
             */
            name: '[name]_library',
            context:__dirname //是解析包路径的上下文,这个要跟接下来配置的 webpack.config.js 一致。
        })
    ]
}
执行 命令【webpack --config webpack-dll-config.js 】就会在 dist 目录下生成 dll bundle 和在根目录生成对应的 manifest文件。manifest 文件的格式大致如下,由包含的 module 和对应的 id 的键值对构成。
接下来通过 DLLReferencePlugin 来使用刚才生成的 DLL Bundle。在默认的webpack-config.js中添加plugins:
new webpack.DllReferencePlugin({
      context: __dirname,//context 需要跟dll中的保持一致,这个用来指导 Webpack 匹配 manifest 中库的路径;
      manifest: require('./manifest.json')
    }),
最后在页面中要引入两个js
<body>
    <script src="dist/vendor.dll.js"></script>
    <script src="dist/bundle.js"></script></body>
使用DLL这样的方式的可以把第三方包和自己的代码包分离,有修改也只需要发布自己的代码包。

关于优化插件OPTIMIZATION

 webpack 提供了一些可以优化浏览器端性能的优化插件,如UglifyJsPlugin,OccurrenceOrderPlugin 和 DedupePlugin,都很实用,也都在消耗构建性能(UglifyJsPlugin 非常耗性能),如果你是在开发环境下,这些插件最好都不要使用,毕竟脚本大一些,跑的慢一些这些比起每次构建要耗费更多时间来说,显然还是后者更会消磨开发者的耐心,因此,只在正产环境中使用 OPTIMIZATION。
 

CommonsChunkPlugin

 当你的 webpack 构建任务中有多个入口文件,而这些文件都 require 了相同的模块,如果你不做任何事情,webpack 会为每个入口文件引入一份相同的模块,显然这样做,会使得相同模块变化时,所有引入的 entry 都需要一次 rebuild,造成了性能的浪费,CommonsChunkPlugin 可以将相同的模块提取出来单独打包,进而减小 rebuild 时的性能消耗。
  同时将多个入口文件相同的js打包处一个共同的后,也可以利用缓存,使加载第二页面的时候不需要再加载共同文件。
commonsPlugin = newwebpack.optimize.CommonsChunkPlugin('common', 'common.[hash].js')
 
 
 
 
posted @ 2019-01-16 17:45  金晶闪闪放光芒  阅读(413)  评论(0编辑  收藏  举报