【Webpack】Webpack4.x

前言

目前为止,webpack 在 GitHub 上已拥有 48.8k 的 star,在前端代码打包器领域内,算得上是 时下最流行的前端打包工具。它可以分析各个模块的依赖关系,最终打包成我们常见的静态文件:.js 、 .css 、 .jpg 、.png,极大地提升了开发至发布过程的效率。所以,不少人称它为:模块打包机。

webpack 工作流程图

一、webpack4.x 的开发环境配置

1. 全局安装 webpack

npm install -g webpack

2. 全局安装 webpack-cli

npm install -g webpack-cli

3. 配置 webpack 的 mode 选项,进行打包

  webpack 的默认入口文件是./src/index.js,默认输出文件./dist/main.js。

// 开发环境
webpack --mode development
// 生产环境
webpack --mode production

4. package.json文件

项目初始化之后,文件夹中会增加 package.json 文件,它用于保存关于项目的信息。我们可以在 package.json 文件中的 script 中配置参数。

配置 dev 和 build

这样可以直接运行 npm run dev / build 来进行打包。

"dev":"webpack --mode development",
"build":"webpack --mode production"

二、webpack4.x 下 babel 的安装、配置及使用

为了实现兼容,需要使用转换工具将ES6语法转换为ES5语法,babel就是最常用的一个工具。那么在webpack中如何使用babel呢?

1. 安装babel-loader、babel-core、babel-preset-env

(1)babel-loader

loader 的作用是让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。

虽然 webpack 本身就能够处理 .js 文件,但无法对ES2015+的语法进行转换,babel-loader 的作用正是实现对使用了ES2015+语法的 .js 文件进行处理。 

npm install -D babel-loader

(2)babel-core

babel-core 的作用在于提供一系列API。这便是说,当 webpack 使用 babel-loader 处理文件时,babel-loader 实际上调用了babel-core 的 API,因此也必须安装 babel-core。

npm install -D babel-core

(3)babel-preset-env

babel-preset-env 的作用是告诉 babel 使用哪种转码规则进行文件处理。事实上,babel 有几种规则都可以实现对ES6语法的转码,如 babel-preset-es2015、babel-preset-latest、babel-preset-env,不过官方现已建议采用 babel-preset-env。

npm install -D babel-preset-env

2. 配置 babel 规则

安装完成之后,还需要配置 babel 规则。

第一种方式是通过 package.json。在 package.json 文件中增加一个“babel"属性,该属性是一个JSON对象,作用是设置项目中的babel 转码规则和使用到的 babel 插件,其基本格式如下:

"babel":{
  "presets": [],
  "plugins": []
}

”presets”属性字段设置转码规则,”plugins”属性设置使用到的插件。我们这里只需将”babel”属性 的”presets”设置为[“env”]即可,如下所示:

"babel":{
  "presets": ["env"]
}

上面的设置告诉 npm 本项目将使用 babel,并且使用 bable-preset-env 规则进行转码,即实现对ES2015+语法进行转码。 

除此之外,还有第二种方式,即通过.babelrc文件。在项目根目录下新建.babelrc文件,里面只需输入第一种方式中”babel”属性的值即可:

{
  "presets": ["env"]
}

3. 建立并配置 webpack.config.js 文件

webpack.config.js 文件的作用是对 webpack 打包的参数进行配置。在根目录下新建 webpack.config.js 文件,在其中输入:

module.exports={
    module:{
        rules:[
            {
                 test: /\.js$/,
                 exclude: /node_modules/, 
                 loader: "babel-loader"
            }
        ]
    }
}

这就告诉 webpack 打包时,一旦匹配到.js文件就使用babel-loader进行处理,如前文所述,babel-loader 调用 babel-core 的API,使用 bable-preset-env 的规则进行转码。这里并没有使用 entry、output 这样的参数,因为 webpack4.x 有默认的入口和出口,我们无须改变,因此便不必进行设置。


一、创建 webpack 配置文件

编写开发环境和生产环境彼此独立的 webpack 配置文件。

新建项目,项目初始化之后,会自动生成 package.json 文件,我们还需要添加三个文件:webpack.common.js、webpack.dev.js、webpack.prod.js。

 webpack-demo
  |- package.json
+ |- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.prod.js
  |- /src
    |- index.js
  |- /node_modules

1. webpack.common.js

安装两个基本插件:

npm i clean-webpack-plugin html-webpack-plugin -D
clean-webpack-plugin:打包时自动清除输出文件夹中未用到的文件
html-webpack-plugin:打包时会自动生成index.html并替换已有的index.html,bundle.js也会自行添加到 html 中
// webpack.common.js
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');  
const HtmlWebpackPlugin = require('html-webpack-plugin');    
    
module.exports = {
    entry: './src/index.js',
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new HtmlWebpackPlugin({
          title: 'index'
        })
    ],
    output: {
        filename: 'bundle.js',           
        path: path.resolve(__dirname, 'dist')    //定义输出文件夹dist路径
    }
};

2. webpack.dev.js

安装 webpack-merge,作用是合并通用配置文件与开发环境配置文件。

npm i webpack-merge -D

安装开发服务器 devServer,作用是修改代码后实时重新加载(刷新浏览器)。

npm i webpack-dev-server -D
// webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
    
module.exports = merge(common,{
    devServer: {                //启用开发服务器
       contentBase: './dist',   //告诉服务器从哪提供内容,只有在想要提供静态文件时才需要
       compress: true,          //一切服务都启用gzip 压缩
       host: '0.0.0.0',         //指定使用一个host,可用ip地址访问,没有的话如果别人访问会被禁止。默认localhost。
       port: '9999',            //指定端口号,如省略,默认为”8080“
       hot: true,               //启用模块热替换特性
       inline: true,            //启用内联模式,一段处理实时重载的脚本被插入到bundle中,并且构建消息会出现在浏览器控制台
       historyApiFallback: true,//开发单页应用时有用,依赖于HTML5 history API,设为true时所有跳转将指向index.html
    },
    plugins: [
         new webpack.HotModuleReplacementPlugin(),  //webpack内置的热更新插件
    ],
    mode: 'development'
});

devServer的更多可选参数:https://www.webpackjs.com/configuration/dev-server/

HotModuleReplacementPlugin 模块热替换(Hot Module Replacement)插件,用以在运行时更新发生改变的模块,从而无需进行完全刷新

3. webpack.prod.js

// webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
    
module.exports = merge(common,{
    mode: "production"
});

关于 mode

  • --mode production 生产环境:不需要像旧版本一样定义 node 环境变量 

自动开启一些插件,如:
uglifyjs-webpack-plugin—— js代码压缩(所以无需再单独使用)
NoEmitOnErrorsPlugin —— 编译出错时跳过输出,以确保输出资源不包含错误
ModuleConcatenationPlugin —— webpack3 添加的作用域提升(Scope Hoisting)

  • --mode development 开发环境:自行定义 node 环境变量为 development 

使用 eval 构建 module, 提升增量构建速度
自动开启一些插件,如:
NamedModulesPlugin 使用模块热替换(HMR)时会显示模块的相对路径

二、启动

在 package.json 文件的 "scripts" 中添加 npm 脚本,从而快捷运行开发服务器 | 打包生产环境代码。

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --open --config webpack.dev.js",
    "build": "webpack --config webpack.prod.js"
},
"start": "webpack-dev-server --open --config webpack.dev.js"
webpack-dev-server    启动开发服务器   
--open    打开浏览器
--config webpack.dev.js    设置运行此脚本时执行的配置文件为 webpack.dev.js
"build": "webpack --config webpack.prod.js"
webpack 启动 webpack
--config webpack.prod.js   设置运行此脚本时执行的配置文件为 webpack.prod.js
执行 npm start

此时应该可以看到 项目输出 。 

执行 npm run build

项目文件夹中自动生成打包后的文件目录(输出文件夹dist)

 webpack-demo
  |- package.json
  |- webpack.common.js
  |- webpack.dev.js
  |- webpack.prod.js
  |- /src
    |- index.js
  |- /dist 
      | - index.html
      | - app.bundle.js
  |- /node_modules

三、使用 sourcemap

sourcemap 能实现打包后的运行代码与源代码的映射,帮助我们debug到原始开发代码。

///webpack.dev.js
module.exports = merge(common,{
    devtool: 'cheap-module-eval-source-map',
    ...
});

大多数时候开发环境用'cheap-module-eval-source-map'是最好的选择,想要完整的功能又不介意构建速度的话就直接用'source-map'。具体的配置项很多,可以是eval,source-map,cheap,module,inline的任意组合。 

具体每个参数的作用请查阅官方API:https://www.webpackjs.com/configuration/devtool/

四、代码分离

把代码分离到不同的 bundle 中,可以按需加载或并行加载这些文件。这样可用于获取更小的 bundle,以及控制资源加载优先级。如果使用合理,会极大影响加载时间。

三种常用的代码分离方法:

1. 入口起点:使用 entry 配置手动地分离代码。

2. 防止重复:使用 SplitChunks 去重和分离 chunk。webpack4 之前版本用的是 CommonsChunkPlugin。

3. 动态导入:通过模块的内联函数调用来分离代码。

更多详情见webpack4.x 配置指南

五、分离CSS

分离 css 需要用到插件 mini-css-extract-plugin,这个插件将会提取 css 到单独的文件,根据每个包含 css 的 js 文件创建一个 css 文件,因此,你的样式将不再内嵌到 JS bundle 中。如果你的样式文件大小较大,这会做更快提前加载,因为 CSS bundle 会跟 JS bundle 并行加载。同时还支持按需加载 css 和 SourceMaps。

相较于旧版 extract-text-webpack-plugin 插件,mini-css-extract-plugin 的优势有:

  • 异步加载
  • 没有重复的编译
  • 更容易使用
  • Specific to CSS
  • 支持热更新

应用情景:

  • 在单个文件中提取所有CSS
  • 按照入口JS来分离CSS
  • 压缩CSS

其他:

  • 这个插件不兼容 style-loader
  • 各种 loader 的处理
  • 区分环境变量 development / production

更多详情见webpack4.x 配置指南

六、缓存

略,详情见webpack4.x 配置指南

七、Babel

略,详情见webpack4.x 配置指南

八、React

略,详情见webpack4.x 配置指南


面试题

  • 有哪些常见的 loader?他们能解决什么问题?

  • webpack 的构建流程是什么? 从读取配置到输出文件的整个过程

  • 是否写过 loader 和 Plugin ?描述一下编写 loader 或 Plugin 的思路?

  • webpack 的热更新是如何做到的?说明其原理?

  • 如何利用 webpack 来优化前端性能?(提高性能和体验)

参考:

webpack4.x 开发环境配置

webpack4.x 下babel的安装、配置及使用

webpack4.x 配置指南

END

猜你喜欢

转载自blog.csdn.net/Dora_5537/article/details/90634252
今日推荐