Webpack知识体系| 青训营笔记

62 阅读6分钟

这是我参与「第四届青训营 」笔记创作活动的第22天

1 DevServer

DevServer 是官方提供的一个开发工具,当我们用webpack搭建一个项目的时候,可能开始的时候是使用本地文件预览的方式来查看我们的页面,而DevServer则不同,它会创建一个http的服务器(默认端口号是8080)并且会帮助我们启动webpack(需要在package.json里面做配置);当服务启动后,DevServer会一直监听此端口,当项目入口文件以及所依赖的文件发生变化的时候,则自行重新编译和刷新页面,

原理大概是 当webpack构建js文件的时候,向js文件注入一个代理客户端用于控制页面,网页和DevServer通过WebSocket协议通信,DevServer所监听的依赖文件发生变化的时候,重新编译文件(当然可以使用模块热替换技术,只编译变化的部分)然后通知注入的代理客户端进行页面刷新。  以上内容一部分是来自webpack深入浅出这本书里面,如有侵权请告知,在这里只是作为本人学习webpack的一个历程而已)

2 MiniCssExtractPlugin (webpack4)

MiniCssExtractPlugin是一个webpack插件 ,作用是将编译后的js文件中的css部分单独提取出来,如果不用这个插件 浏览器渲染出来的页面css部分将是通过在页面头部假如style标签形成,如果用了,则是通过外部文件引入的形式加载css文件

主要的优点有:异步加载,不重复编译,性能更好,只针对CSS,

缺点:不支持HMR (hot module replace)

3 在开发环境css样式都是正常,在生产化境就不生效的踩坑记录

1 tree shaking 会检测项目中那些文件没有被依赖,从而删除它,以提高编译性能,所以当我们在引如一个有副作用的文件的时候,(比如css文件)需要给webpack一个标记,用sideEffects 表示,在package.json中加入下面代码

  "sideEffects":[ "*.css"],

如果项目中引入的没有被依赖的文件都无副作用 直接

 "sideEffects"false,

如果是某个特定的js文件 ,直接在数组中加入文件的路径就好

  "sideEffects":[ "./src/some-side-effectful-file.js"],

\

4 在配置webpack过程中一些提高性能的小技巧

1 在配置webpack的时候尽量不要生产环境和开发环境用同一个配置文件(webpack.config.js) 在你的项目根目录下面新建webpack.dev.js, webpack.prod.js和webpack.common.js。当然这个名字自己随便写,然后下载一个webpack-merge工具(对象合并用的 npm下载就好)然后在package.json中的script下面配置启动命令

    "build": "webpack --config webpack.prod.js",
    "start": "webpack-dev-server --open --config webpack.dev.js"

然后在webpack.dev.js和webpack.prod.js中引入webpack.common.js

const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');
module.exports=merge(common,{
    devtool: 'inline-source-map',
    mode: 'development',
    devServer: {
        contentBase: './dist',
        hot:true
    },
    resolve:{
        alias:{
            static:path.resolve(__dirname,'src/static')
        }
    }
})

然后如果需要在开发环境用的配置直接在webpack.dev.js文件中配置,生产环境就在webpack.prod.js中配置,公共配置就放在webpack.common.js中配置。

优点就是在本地开发的时候做的一些有利于调试和开发方便的配置,不至于影响生产环境的编译性能。

2 在配置loader的时候尽量将同一种作用或者类型的文件放在同一个文件,然后在利用loader编译的时候配置一个include属性,比如css,就告诉wenpack在那个具体的文件中找就可以,而不用全局递归处理,

  module: {
        rules: [
            {
                test: /.css$/,
                use: [MiniCssExtractPlugin.loader,'css-loader'],
                include: path.resolve(__dirname,'src/static/css')
            },
            {
                test: /.(png|svg|jpg|gif)$/,
                use: ['file-loader']
            }
        ]
    },

3 在配置module的时候如果有一些文件没有采用模块化的思想(比如 jquery,chartjs) 则配置一个noParse忽略对这些文件的递归解析和处理 以减少构建时间

  module: {
    noParse: /jquery|chartjs/,
  }

或者可以通过一个函数处理

  module: {
    noParse: (content) => /jquery|lodash/.test(content)
  }

4 代码压缩

浏览器通过服务器访问网页时获取js,css资源都是通过文本形式的,文件越大,网页加载时间越长,为了提升网页加载速度和节省传输流浪,我们需要将代码压缩,比如通过GZIP算法对文件进行压缩,或者压缩文件本身,比如利用webpack的UglifyJsPlugin和ParallelUglifyPlugin来压缩JS文件

提高构建速度

1 在多入口的情况下使用CommonsChunkPlugin来提取公共代码,避免重复编译打包

2 使用happypack实现多进程加速打包

3 使用Tree-shaking和Scope Hoisting来删除多余的代码

实现多页应用

使用AutoWebPlugin来完成简单的自动化的构建

npm 打包时需要注意什么

1 要支持CommonJS模块化规范,所以要求打包后的最后结果也遵守该规则

2 Npm模块使用者的环境是不确定的,很有可能并不支持ES6,所以打包的最后结果应该是采用ES5编写的

3 发布的模块不能将依赖的模块也一同打包,应该让用户选择性的去自行安装。这样可以避免模块应用者再次打包时出现底层模块被重复打包的情况。

\

\

5 webpack监听文件的两种方式

1 Watch

在配置文件中 Watch:true; 通过WatchOptions进行更加详细的配置,(代码变更后自行打包)

    watch:true,
    watchOptions:{
       ignored:/node_modules/,  //不需要监听的文件
       aggregateTimeout:300,  //编译的频率 300毫秒编译一次
        poll:1000 //询问指定文件的频率 每秒询问1000次
    },

在package.json中配置 如下

 "scripts": {
    "watch": "webpack --watch" 
  }

然后在终端通过 npm run watch启动项目 (如果你的webpack配置文件是自定义的,则需要后面将参数跟上) 比如

"scripts": {
    "watch": "webpack --watch --config webpack.dev.js" 
  }

监听原理

webpack通过配置文件的入口将所有依赖文件形成一个监听列表(包括第三方模块)然后定时的去记录这些文件的最后一次编辑的时间,如果发现和上次的编辑时间不一样,则认为此文件已经被编辑,然后重新编译。当然这个查询周期我们可以配置watchOptions.poll,并贴编译的延迟时常也可以配置watchOptions.aggregateTimeout,对于一些第三方包,我们是一般不编辑的,所以可以将第三包移出监听队列里面,watchOptions.ignored

2 devServer 默认开启监听 (在热更新后,代码没有打包,如果需要打包,还是要进行步骤2的操作)