zoukankan      html  css  js  c++  java
  • 【webpack系列】从零搭建 webpack4+react 脚手架(二)

    html文件如何也同步到dist目录?bundle.js文件修改了,万一被浏览器缓存了怎么办?如何为导出的文件加md5?如何把js引用自动添加到html?非业务代码和业务代码如何分开打包?如何搭建开发环境?如何实现开发环境的热更新?

    在上一节我们已经搭建了一个最基本的webpack环境, 这一节我们带着上节的一些疑问,继续优化我们的react工程。
     
    1.整合html-webpack-plugin
     
    public的index.html应该自动编译到dist目录,并且所有的js引用是自动添加的。你可以使用html-webpack-plugin插件来处理这个优化。
    (1)安装html-webpack-plugin:
    npm install --save-dev html-webpack-plugin
    (2)在webpack.prod.conf.js中配置plugins属性。
        const merge = require('webpack-merge');
        const baseWebpackConfig = require('./webpack.base.conf.js');
        const HtmlWebpackPlugin = require('html-webpack-plugin');
    
        module.exports = merge(baseWebpackConfig, {
            mode: 'production',
            plugins: [
                new HtmlWebpackPlugin({
                    template: 'public/index.html',
                    inject: 'body',
                    minify: {
                        removeComments: true,
                        collapseWhitespace: true,
                        removeAttributeQuotes: true
                    },
                })
            ]
        });
    (3)删除index.html中手动引入的script标签

    index.html的代码应该是这样的:

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>从零开始搭建react工程</title>
        </head>
        <body>
        <div id="root"></div>
        </body>
        </html>
    (4)重新执行编译
    npm run build

    查看dist文件夹,index.html也被加载进来了,并且已经自动加上了script标签。

    2.为导出的js文件添加内容hash
     
    当我们的业务有修改,bundle被重新打包,很可能在客户的电脑上并没有奏效,你告诉客户,应该是被缓存了,需要刷新浏览器,清理下浏览器缓存。这也许能解决问题,但是太糟糕了,我们有更好的方式,让导出的js文件加上文件hash,从而每次修改,转译出的js文件名称都不相同,那么js文件当然不会被缓存了。
    添加文件hash的方法很简单,只要修改 output.filename 属性即可,这里我们做一个小小的优化,把导出的文件存放在js目录下,并且直接使用name+chunkhash的方式来命名。
    filename: "js/[name].[chunkhash:16].js"
    其中,name就是模块名称,我们在entry中进行过配置,chunkhash是文件内容的hash,webpack默认采用md5的方式对文件进行hash。16是hash的长度,如果不设置,webpack会设置默认值为20。
    现在,你的webpack.prod.conf.js文件看起来应该是这样:
        const merge = require('webpack-merge');
        const baseWebpackConfig = require('./webpack.base.conf.js');
        const HtmlWebpackPlugin = require('html-webpack-plugin');
    
        module.exports = merge(baseWebpackConfig, {
            mode: 'production',
            output: {
                filename: "js/[name].[chunkhash:16].js",
            },
            plugins: [
                new HtmlWebpackPlugin({
                    template: 'public/index.html',
                    inject: 'body',
                     minify: {
                        removeComments: true,
                        collapseWhitespace: true,
                        removeAttributeQuotes: true
                    },
                })
            ]
        });
    3.编译前清理dist目录
     
    现在,如果你修改了你的业务代码,然后重新编译,你会发现在dist/js文件夹出现多个js文件。因为导出的js文件hash已经不相同,每次编译都会增加新的js文件,原来的文件没有被删除。所以,我们需要在编译前进行清理dist文件夹。
    (1)安装clean-webpack-plugin
    npm install --save-dev clean-webpack-plugin
    (2)修改webpack.prod.conf.js,使用clean-webpack-plugin
        const merge = require('webpack-merge');
        const baseWebpackConfig = require('./webpack.base.js');
        const HtmlWebpackPlugin = require('html-webpack-plugin');
        const CleanWebpackPlugin = require('clean-webpack-plugin');
    
        module.exports = merge(baseWebpackConfig, {
            mode: 'production',
            output: {
                filename: "js/[name].[chunkhash:16].js",
            },
            plugins: [
                new HtmlWebpackPlugin({
                    template: 'public/index.html',
                    inject: 'body',
                    minify: {
                        removeComments: true,
                        collapseWhitespace: true,
                        removeAttributeQuotes: true
                    },
                }),
                new CleanWebpackPlugin(['../dist'], { allowExternal: true })
            ]
        });
    (3)执行试试看
    npm run build

    编译过程,注意查看控制台输出,你会发现webpack删除了dist目录。

    4.非业务代码单独打包
     
    在build结束,webpack会在终端显示打包文件的大小,我们可以看到这个app.js包大概在96.9KB

    随着我们业务代码的增加,这个包将会越来越大。
    你每次发布,这个文件都会被重新下载。你的代码有修改,用户需要重新下载无可厚非。可是,你别忘了这个app.js内还包含了很多不变的代码,比如react,react-dom。我们需要把这些不变的代码分开打包。
    在webpack.base.conf.js,我们添加一个入口配置。entry有2个入口。

        entry: {
                app: './app/index.js',
                framework:['react','react-dom'],
            },

    重新执行npm run build,再看看。

    的确,react和react-dom 被编译成framework.js。可是,你会发现,app.js并没有减少,还是96.9KB。因为我们还缺少一步,就是抽离app.js中公共的代码。
    webpack3版本是通过配置CommonsChunkPlugin插件来抽离公共的模块。webpack4版本,官方废弃了CommonsChunkPlugin,而是改用配置optimization.splitChunks的方式,更加方便。
    在webpack.prod.conf.js增加如下代码:

        optimization: {
                splitChunks: {
                    chunks: "all",
                    minChunks: 1,
                    minSize: 0,
                    cacheGroups: {
                        framework: {
                            test: "framework",
                            name: "framework",
                            enforce: true
                        }
                    }
                }
            }

    cacheGroups对象,定义了需要被抽离的模块,其中test属性是比较关键的一个值,他可以是一个字符串,也可以是正则表达式,还可以是函数。如果定义的是字符串,会匹配入口模块名称,会从其他模块中把包含这个模块的抽离出来。name是抽离后生成的名字,和入口文件模块名称相同,这样抽离出来的新生成的framework模块会覆盖被抽离的framework模块,虽然他们都叫framework。
    重新执行npm run build你看到app.js的体积变小了 才1kb。

    注意查看生成的文件的hash,接下去我们随意修改app/index.js的代码。重新执行npm run build编译。看看编译后的结果:

    看到了吗,app的hash发生了改变(它不能被浏览器缓存),而framework没有改变(它会被浏览器缓存),这达到了我们预期的结果。

    5.压缩js文件
     
    打开build后的js文件看看,js文件没有被压缩。在prod环境,我们希望js已经被压缩了,这样做的好处是减少文件体积,更快地被用户加载。js压缩,用到了uglifyjs-webpack-plugin,在optimization内进行配置。
    (1)安装uglifyjs-webpack-plugin
    npm install --save-dev uglifyjs-webpack-plugin
    (2)在webpack.prod.conf.js页面上引入
    const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
    (3)optimization内配置minimizer参数
        minimizer: [
            new UglifyJSPlugin()
        ],

    你的optimization参数现在应该是这样:

         optimization: {
                minimizer: [
                    new UglifyJSPlugin()
                ],
                splitChunks: {
                    chunks: "all",
                    minChunks: 1,
                    cacheGroups: {
                        framework: {
                            priority: 200,
                            test: "framework",
                            name: "framework",
                            enforce: true,
                            reuseExistingChunk: true
                        },
                        vendor: {
                            priority: 10,
                            test: /node_modules/,
                            name: "vendor",
                            enforce: true,
                            reuseExistingChunk: true
                        }
                    }
                }
            }
    (4)重新执行npm run build
    npm run build
    6.整合dev环境
     
    我们不可能每次修改代码都去手动编译,等编译出来再去打开文件查看效果。webpack提供了开发环境服务,并且支持热更新,这在开发环境是非常有必要的。
    webpack-dev-server这个模块提供了开发服务的支持,通过在webpack.dev.conf.js文件配置devServer可以方便地整合webpack-dev-server。
    (1)安装webpack-dev-server
    npm install --save-dev webpack-dev-server
    (2)在build中添加webpack.dev.conf.js文件
        const path = require('path');
        const merge = require('webpack-merge');
        const baseWebpackConfig = require('./webpack.base.conf.js');
        const HtmlWebpackPlugin = require('html-webpack-plugin');
        const webpack = require('webpack');
    
        module.exports = merge(baseWebpackConfig, {
            mode: 'development',
            output: {
                filename: "js/[name].[hash:16].js",
            },
            plugins: [
                new HtmlWebpackPlugin({
                    template: 'public/index.html',
                    inject: 'body',
                    minify: {
                        html5: true
                    },
                    hash: false
                }),
                new webpack.HotModuleReplacementPlugin()
            ],
            devServer: {
                port: '8080',
                contentBase: path.join(__dirname, '../public'),
                compress: true,
                historyApiFallback: true,
                hot: true,
                https: false,
                noInfo: true,
                open: true,
                proxy: {}
            }
        });

    HotModuleReplacementPlugin是webpack热更新的插件,设置devServer.hot为true,并且在plugins中引入HotModuleReplacementPlugin插件即可。
    还需要注意的是我们开启了hot,那么导出不能使用chunkhash,需要替换为hash。

    (3)在package.json增加一个npm scripts
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    (4)执行dev命令
    npm run dev

    打开 http://localhost:8080 查看,你可以尝试改动index.js的代码,浏览器自动更新了,说明整合webpack-dev-server成功。
    你可能注意到,对于css相关的技术栈,我只字未提,别急,下一节我们会详细针对css相关的技术栈进行整合。

  • 相关阅读:
    Asp.NET 4.0 ajax实例DataView 模板编程1
    ASP.NET 4.0 Ajax 实例DataView模板编程 DEMO 下载
    部分东北话、北京话
    .NET 培训课程解析(一)
    ASP.NET 4.0 Ajax 实例DataView模板编程2
    ASP.NET Web Game 架构设计1服务器基本结构
    ASP.NET Web Game 构架设计2数据库设计
    TFS2008 基本安装
    Linux上Oracle 11g安装步骤图解
    plsql developer远程连接oracle数据库
  • 原文地址:https://www.cnblogs.com/nianzhilian/p/10229122.html
Copyright © 2011-2022 走看看