【webpack系列】从零搭建 webpack4+react 脚手架(二)

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相关的技术栈进行整合。

以上是 【webpack系列】从零搭建 webpack4+react 脚手架(二) 的全部内容, 来源链接: utcz.com/z/381458.html

回到顶部