02-Webpack4配置增强

作者: 七玄之主 | 来源:发表于2019-06-20 17:27 被阅读15次

    我们已经完成了基于React的脚手架工程的创建,现在让我们来进一步增强我们的工程,已方便日后的开发。

    增强Webpack

    清理 /dist 文件夹

    dist文件夹里包含了我们生成的各种打包文件,我们更新生成配置后,如果不即使删除里面的残留文件,可能导致旧打包文件和新打包文件共存的情况。

    我们可以在编译时添加脚本删除,如下所示:

    "build": "rd /S /Q dist && webpack"
    

    也可以通过Webpackclean-webpack-plugin插件来实现。

    安装插件yarn add -D clean-webpack-plugin

    修改webpack.config.js文件,加入html-webpack-plugin插件

        // 管理插件,通过插件实现增强功能
        plugins: [
            // 每次编译前清除dist文件夹
            new CleanWebpackPlugin(),
        ],
    

    区分开发和生成环境

    开发环境(development)和生产环境(production)的构建目标差异很大。在开发环境中,我们需要具有强大的、具有实时重新加载(live reloading)或热模块替换(hot module replacement)能力的 source map 和 localhost server。而在生产环境中,我们的目标则转向于关注更小的 bundle,更轻量的 source map,以及更优化的资源,以改善加载时间。由于要遵循逻辑分离,我们通常建议为每个环境编写彼此独立的 webpack 配置。
    基于以上原理,我们将原有的webpack.config.js一个配置文件分割为webpack.common.jswebpack.dev.jswebpack.prod.js三个配置文件。

    首先安装yarn add -D webpack-merge

    根据原有webpack.config.js文件将对应配置分散到三个配置文件中

    webpack.common.js

    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    const webpack = require('webpack')
    
    module.exports = {
        // 入口文件
        entry: './src/index.tsx',
        // 需要解析的文件后缀名
        resolve: {
            extensions: ['.tsx', '.ts', '.js']
        },
        // 管理插件,通过插件实现增强功能
        plugins: [
            // 自动清理dist
            new CleanWebpackPlugin(),
            // 根据模板生成html
            new HtmlWebpackPlugin({
                title: 'My App',
                template: './src/index.html'
            }),
        ],
        // 配置项目处理的不同文件及模块
        module: {
            rules: [
                {
                    test: /\.(ts|tsx)?$/,
                    loader: 'awesome-typescript-loader'
                },
            ]
        }
    };
    

    webpack.dev.js

    const merge = require('webpack-merge')
    const common = require('./webpack.common.js')
    const webpack = require('webpack')
    const path = require('path');
    
    module.exports = merge(common, {
        // 标识配置为开发用
        mode: 'development',
        // 控制是否生成,以及如何生成 source map
        devtool: 'cheap-module-eval-source-map',
        // 管理开发服务器
        devServer: {
            // 查找文件路径
            contentBase: 'dist',
            // 启用 HMR
            hot: true,
        },
        plugins: [
            // 当开启 HMR 的时候使用该插件会显示模块的相对路径,建议用于开发环境
            new webpack.NamedModulesPlugin(),
            // 启用 HMR 热更新,建议用于开发环境
            new webpack.HotModuleReplacementPlugin()
        ],
        // 管理输出
        output: {
            // 定义输出文件名规则
            filename: '[name].bundle.js',
            // 定义输出文件名路径
            path: path.resolve(__dirname, 'dist'),
        },
    })
    

    webpack.prod.js

    const merge = require('webpack-merge')
    const common = require('./webpack.common.js')
    const webpack = require('webpack')
    const path = require('path');
    
    module.exports = merge(common, {
        // 标识配置为生产用
        mode: 'production',
        // 控制是否生成,以及如何生成 source map
        devtool: 'source-map',
        // 管理输出
        output: {
            // 定义输出文件名规则
            filename: '[name].[contenthash].js',
            // 定义输出文件名路径
            path: path.resolve(__dirname, 'dist'),
        },
    })
    

    最后修改package.json

    "scripts": {
        "build": "webpack --config webpack.prod.js",
        "dev": "webpack-dev-server --config webpack.dev.js"
      },
    

    Source Map说明

    Webpack的打包过程中,会对源代码进行压缩,合并,编译等操作,导致编译后的代码和源码差异较大。为了更容易地追踪错误和警告,通过JavaScript 提供的source map功能,能够将编译后的代码映射到源代码上,便于错误定位。

    Webpack中,是通过devtool配置项来指定构造的source map类型。配置项很多,但大致可以划分为5类,其余配置项可以是其任意组合。

    • eval: 使用eval包裹模块代码,尾部通过souceURL来定位原始代码位置,不产生.map文件
    • source-map: 产生.map文件,通过.map文件定位
    • cheap: 不包含列信息(debug时注意点都在行数上,不用关心列数)也不包含loader的sourcemap(意味着如果使用了类似bable类编译工具,定位到的就是编译后的代码而非原始代码)
    • module: 包含loader的sourcemap(比如babel的sourcemap)
    • inline: 将.map作为DataURI嵌入,不单独生成.map文件

    综上所示,我们在开发环境选用cheap-module-eval-source-map,就能够定位到各个原始文件上。生产环境则考虑使用source-map

    代码压缩

    Webpack4的mode是production时,会自动开启js的压缩,不过这里我们还是使用uglifyjs-webpack-plugin插件。

    安装

    yarn add -D uglifyjs-webpack-plugin

    修改webpack.prod.js文件

    module.exports = merge(common, {
        // 标识配置为生产用
        mode: 'production',
        // 控制是否生成,以及如何生成 source map
        devtool: 'source-map',
        plugins: [
            new UglifyJSPlugin({
                sourceMap: true
            }),
        ],
        // 管理输出
        output: {
            // 定义输出文件名规则
            filename: '[name].[contenthash].js',
            // 定义输出文件名路径
            path: path.resolve(__dirname, 'dist'),
        },
    })
    

    这里需要注意一点,UglifyJSPlugin压缩插件不能解析es6语法,需要引入bable来处理es6,es7的js文件的编译。

    指定环境

    程序中使用的某些第三方library可能会和process.env.NODE_ENV环境变量关联,比如在生产环境中增加额外的日志记录或测试,在生产环境中增加一些优化。因此我们根据不同的环境预设好process.env.NODE_ENV的值。NODE_ENV本质上是Node.js露给执行脚本的系统环境变量,同时并不能在Webpack.prod.js类似的构建脚本中预设NODE_ENV的值,但我们可以通过webpack内置的 DefinePlugin为所有的依赖定义这个变量。

    对应环境的webpack配置文件中增加如下所示的插件配置:

    // 预设程序执行环境
    new webpack.DefinePlugin({
          'process.env.NODE_ENV': JSON.stringify('production')
    })
    

    相关文章

      网友评论

        本文标题:02-Webpack4配置增强

        本文链接:https://www.haomeiwen.com/subject/mfujqctx.html