webpack-常用plugin

1,240 阅读4分钟

接上篇loader继续 这次是plugin

LIST

HtmlWebpackPlugin

htmlwebpackplugin会在打包结束后,自动生成一个html文件,并把打包生成的js模块引入到该html中。
npm install --save-dev html-webpack-plugin安装

// 修改webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    ...
    plugins: [
        new HtmlWebpackPlugin({
            // filename: 'index_min.html' // 编译之后的文件名 
            template: './index.html' //设置以哪个文件为模板
        })
    ]
    ...
}

clean-webpack-plugin

clean-webpack-plugin打包前自动清空dist目录
npm install --save-dev clean-webpack-plugin

// 修改webpack.config.js
const cleanWebpackPlugin = require('clean-webpack-plugin')

module.exports = {
    ...
    plugins: [
        new HtmlWebpackPlugin({
            // filename: 'index_min.html'
            template: './index.html'
        }),
        new cleanWebpackPlugin()
    ],
    ...
}

ExtractTextWebpackPlugin

ExtractTextWebpackPlugin 会将css、less、sass文件打包成单独的文件 用link标签方式引入到html中 会将css文件都合并到一个文件中 less文件合并到一个文件中

npm install --save-dev extract-text-webpack-plugin@next安装一个最新版本 现在这个插件的3版本的 有用的API已经废弃

// 修改webpack.config.js
// 创建多个实例 因为我们的案例里既有css 又有less
const extractCSS = new ExtractTextPlugin('stylesheets/[name]-css.css');
const extractLESS = new ExtractTextPlugin('stylesheets/[name]-less.css');

module.exports = {
    ...
    plugins: [
        ...
        extractCSS,
        extractLESS
    ],
        module: {
        rules: [
            ...
            {
                test: /\.css$/,
                use: extractCSS.extract(['css-loader', 'postcss-loader']),
            },
            {
                test: /\.less$/,
                use: extractLESS.extract(['css-loader', 'postcss-loader', 'less-loader']),
            }
        ]
    }
}
    ...
}

// 我们再创建个css文件 在index.js中引用 然后进行编译 会发现生成了两个css文件 一个是css后缀打包的文件,一个是less后缀打包的文件 也就是说我们在index.js引入的两个css后缀的文件被放到了一个文件中

打包后的文件 打包前的css文件

sourceMap

源代码与打包后的代码的映射关系 可以看到具体的报错和输出位置在哪个文件哪一行
首先我们在配置文件中生命mode: 'development',这样可以便于debug
在dev模式中,默认开启,关闭的话 可以在配置里件devtool:"none"

eval:速度最快
cheap:较快,不用管列的报错
Module:第三方模块
开发环境推荐:

devtool:"cheap-module-eval-source-map"
线上环境可以不开启:如果要看到一些错误信息,推荐;
devtool:"cheap-module-source-map"

WebpackDevServer

提升开发效率的利器
每次改完代码都需要重新打包一次,打开浏览器,刷新一次,很麻烦
我们可以安装使用webpackdevserver来改善这块的体验

npm install webpack-dev-server -D安装
修改下package.json 加个启动命令

"scripts": {
    "server": "webpack-dev-server"
},

在webpack.config.js配置:

devServer: {
    contentBase: "./dist", // 把服务器启动在dist文件下
    open: true, // 自动打开浏览器
    port: 8081  // 端口号
},

使用npm run server启动
启动服务后,会发现dist目录没有文件,这是因为devServer把打包后的模块不会放在dist目录下,而是放在到内存中,从而提升速度

解决开发阶段本地请求跨域

先来创建一个跨域环境,用express模拟一个后端api接口

// npm i express -D
// 创建server.js
const express = require('express')
const app = express()
app.get('/api/info', (req, res) => {
    res.json({
        content: '测试跨域请求'
    })
})
app.listen('9092')
// node server.js

然后在index.js中请求该接口

import axios from 'axios'
 axios.get('http://localhost:9092/api/info').then(res=>{
     console.log(res)
 })

我们可以看到结果实际上是跨域了 在正式环境我们会用cors或者nginx代理,在开发环境webpack-dev-server也提供了代理功能,可以做代理处理

// 修改webpack.config.js
devServer: {
    ...
    proxy: {
        "/api": {
            target: "http://localhost:9092"
        }
    }
},

// 修改index.js 去掉协议
import axios from 'axios'
 axios.get('api/info').then(res=>{
     console.log(res)
 })

这样请求就可以正常过来了

Babel处理ES6

官方链接babeljs.io/
npm i babel-loader @babel/core @babel/preset-env -D安装
babel-loader是webpack与babel的通信桥梁,不会做把es6转成es5的工作,这部分工作需要用到@babel/preset-env来做,@babel/preset-env里包含了es6转es5的转换规则

// 在index.js中加一些es6语法
const arr = [new Promise((resolve) => { resolve(1) }), new Promise((resolve) => { resolve(1) })]

然后我们使用npx webpack编译,这里是为了看下编译后的文件,就没采用webpack-dev-server去做编译。

我们可以看到build.js文件中编译的结果,const ()=>{}都得到了编译,但是promise并没有编译

所以上面这步还不够,Promise等一些还有转换过来,这时候需要借助@babel/polyfill,把es的新特性都装进来,来弥补低版本浏览器中缺失的特性
npm install --save @babel/polyfill安装

// index.js最上方引入@babel/polyfill
import "@babel/polyfill";

我们再进行编译 我们对比之前的文件,发现整体文件大了好多,,这是因为polyfill默认会把所有特性注入进来 所以我们考虑按需引入

// 去掉index.js中的引用

// 修改配置 webpack.config.js
{
    test: /\.js$/,
    exclude: /node_modules/,
    loader: "babel-loader",
    options: {
        presets: [
            [
                '@babel/preset-env',
                {
                    useBuiltIns: "usage", //按需注入
                    corejs: 3
                }
            ]
        ]
    }
}

打包后明显小了很多 当我们开发的是组件库,工具库这些场景的时候,polyfill就不适合 ,因为polyfill是注入到全局变量, window下的,会污染全局环境,所以推荐闭包方式:@babel/plugin-transform-runtime

// 安装
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime

// 修改配置
// presets: [
//     [
//         '@babel/preset-env',
//         {
//             useBuiltIns: "usage", //按需注入
//             corejs: 3
//         }
//     ]
// ]
plugins: [
    [
        "@babel/plugin-transform-runtime",
        {
            "corejs": 2,
        }
    ]
]

.babelrc文件,就是将options里的内容移到外面来

配置React打包环境

npm install react react-dom --save安装

// 我们创建一个react.js用import或require把这个文件引入到index.js中
// react.js
import React, { Component } from "react";
 import ReactDom from "react-dom";
 class App extends Component {
   render() {
     return <div>hello world</div>;
   }
 }
 ReactDom.render(<App />, document.getElementById("app"));

安装babel与react转换的插件:
npm install --save-dev @babel/preset-react
然后修改配置文件

// webpack.config.js
{
    test: /\.js$/,
    exclude: /node_modules/,
    loader: "babel-loader",
    options: {
        presets: [
            [
                '@babel/preset-env',
                {
                    useBuiltIns: "usage", //按需注入
                    corejs: 3
                },
            ],
            "@babel/preset-react"
        ]
        // plugins: [
        //     [
        //         "@babel/plugin-transform-runtime",
        //         {
        //             "corejs": 2,
        //         }
        //     ]
        // ]
    }
}

然后进行编译,打开页面可以看到我们的react组件可以正常显示