前言
create-react-app是个优秀的脚手架工具,然而作为前端开发者,不能不会自己搭建脚手架工具。所以,开始了学习webpack之路。
首先,大体了解webpack的工作流程
打包就是将文件打包为另一个文件的能力。webpack将打包过程视为输入、输出两部分,其中这个过程还包括入口、模块、chunk、chunk组合和许多其他部分。从入口开始,webpack会创建一个依赖关系图,这个关系图中包含着应用程序中所需的所有模块,然后打包为bundle。
了解了之后,我们开始正式构建脚手架工具。
- 首先进行基础配置,设置入口和出口。
配置文件为webpack.config.js 安装npm install webpack webpack-cli webpack-dev-server. 我这里使用的是webpack4的版本。小伙伴们,请根据需要调整。
const path = require('path')
module.exports = {
entry: 'src/index.js', // 入口
output: {
path: path.resolve(__dirname, 'dist'), // 输出目录
publicPath: '/dist/', // 加载资源的目录
filename: 'bundle.js' // 输出文件名
}
}
我们的目录结构为:
--public
----index.html
----logo.jpeg
--src
-----index.js
-----App.jsx
-----App.css
--webpack.config.js
--.babelrc
- 配置webpack使其能打包css、jpeg和jsx文件。
webpack默认是只能打包js文件的。我们需要用不同的loader来增强它的打包能力。 使用stley-loader(自动生成style标签)、css-loader来打包css文件。 使用url-loader、file-loader打包图片资源文件。 同时为了使用es6等语法,使用babel-loader打包js、jsx文件。 webpack配置如下:
module.exports = {
...,
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.(png|jpeg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
}
]
},
resolve: {
extensions:['*', '.js', '.jsx'] // 设置按顺序解析文件名
}
}
配置resolve.extensions属性的含义是:
当使用import * from 'src/App'时,会先按照无后缀名匹配,然后App.js,如果找不到就按照App.jsx匹配文件。
babel的配置如下:
{
"presets": ["@babel/env", "@babel/preset-react"],
"plugins": [
"@babel/plugin-proposal-optional-chaining"
]
}
- 自动生成html文件
每次打包之后都会生成bundle.js文件,如果改变打包路径的话,就需要手动改HTML文件中的script标签的src属性,为了方便,使用html-webpack-plugin自动生成HTML文件。 npm install html-webpack-plugin --save-dev
...
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
title: 'webpack for react', // 设置title变量,可以在index.html中读取
template: 'public/index.html' // 模板文件
})
]
}
html-webpack-plugin还有很多有用的配置,比如设置变量等。在这里设置了title变量,在HTML文件中可以使用<%= htmlWebpackPlugin.options.title %>读取这个变量的值。
- 使用clean-webpack-plugin清理打包文件。
如果不清理打包文件,那么每次打包构建后的文件夹dist目录中会有很多多余的文件。 不再介绍如何安装插件。
...
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
//...
plugins: [
//...
new CleanWebpackPlugin()
]
}
- 设置webpack-dev-server启动本地服务
开发过程中,大部分时间都是在本地调试,webpack-dev-server提供了本地启动服务的方式。
//...
devServer: {
contentBase: path.join(__dirname, 'dist'), // 设置代理目录
port: 3000,
publicPath: 'http://localhost:3000/dist/', // 设置打包文件url,可以直接写/dist/
hotOnly: true, // 热更新
compress: true, // 压缩
open: true, // 自动打开浏览器
writeToDisk: true, // webpack-dev-server默认是将文件存在内存里,这里设置为存在磁盘中
proxy: { // 设置代理
api: 'http://localhost:3000'
/* 'api': {
target: 'http://localhost:3000',
pathRewrite: {
'^/api': ''
}
} */
}
// host: '127.0.0.1' // 修改dev server的host
},
- 设置每次webpack-dev-server重新打包时保留index.html文件
这是启动本地服务后,每次webpack-dev-server重新打包,并不会再次生成index.html文件,而clean-webpack-plugin会将原来的html删除掉,所以为clean-webpack-plugin增加配置,使得每次打包后clean时并不删除index.html文件。
module.exports = {
// ...
plugins: [
new CleanWebpackPlugin({
/* 使得每次webpack-dev-server打包之后,index.html文件仍然保留 */
cleanStaleWebpackAssets: false
})
]
}
- 将css文件提取出来
css-loader会将css打包到js中,然后再由style-loader生成style标签。现在我使用mini-css-extract-plugin将css提取出来到单独的文件中。 总共有两步:
- 替换loader
- 增加plugin
module.exports = {
// ...
module: {
rules: {
{
test: /\.css$/,
// 将style-loader替换为MiniCssExtractPlugin.loader
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
// ...
}
},
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'css/[name].css',
chunkFilename: 'css/[id].css'
})
]
}
- 配置热更新
模块热替换(HMR - hot module replacement)功能会在应用程序运行过程中,替换、添加或删除模块,而无需重新加载整个页面。 但是,模块热更新绝不能用在生产环境中。 所以,要先判断是否为生产环境,如果是,则启用;否则,不启用。
// 设置运行环境
const mode = process.env.NODE_ENV
const plugins = []
if (mode !== 'production') {
// 设置热更新插件只在开发模式下启用,HMR决不能用在生产环境中
const hotModuleReplacementPlugin = new webpack.HotModuleReplacementPlugin()
plugins.push(hotModuleReplacementPlugin)
}
module.exports = {
plugins: [
..plugins,
// ...
]
}
- 启用sourceMap
一般来讲,生产环境和开发环境的考虑的因素不同,所以对于sourceMap的需求也不同。我这里配置的开发环境的sourceMap主要考虑的准确性,生产环境没有配置sourceMap。
//...
module.exports = {
// ...
devtool: mode === 'development' ? 'eval-source-map' : 'none'
}
- 处理热更新辅助文件
每次热更新都会生成后缀名为.hot-update.js和.hot-update.json的辅助文件。热更新的次数多了之后,这些辅助文件也相应的多了。我们进行配置,只保留最新的辅助文件。
module.exports = {
output: {
// ...
/* 避免HotModuleReplacementPlugin每次都生成不同的描述文件json和补丁文件js */
hotUpdateChunkFilename: 'hot/hot-update.js',
hotUpdateMainFilename: 'hot/hot-update.json'
}
}
至此,简易的脚手架搭建完毕,当然还有很多缺失,比如对字体的处理、相同模块的提取等等,但是骨架已经出来,大家可以根据这个进行简单学习。 git地址
欢迎大家批评指正。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!