需求
最近公司又开发一个app,本来没我前端啥事的,需求评审都没我份,我也懒得参加,可是开发到半路,需求改来改去后,还是要前端写两个h5页面配合一下。一个h5邀请注册页面,一个app下载页面,页面很简单,活不多,用框架又增加打包体积,想来想去还是亲手用原生js和配置webpack来搞定它吧,考验脱离框架、库开发出精简业务代码的时候到了。
为什么要用webpack?
理由:
- 为了项目可持续化、可维护、可扩展等也就是我们经常说的前端工程化。webpack可以说是前端工程化进程的产物了,里面种种好处不一一列举,以前那种手写html\css\js的年代一去不复返了,那种弊端太多了。
- 闲的没事干&&巩固一下webpack知识。
设计稿


架构
webpack多页面配置,js语法es6,样式预处理器scss。
环境要区分development,test,production三个环境。其中development是我们启动webpack-dev-server开发的环境,test是打包到测试环境,production是打包到线上环境,因为注册页面有两个接口,一个发送验证码,一个注册接口。
webpack基本配置概念:
entry配置入口文件js,
output配置出口,
loader处理各种文件格式转换,
plugin在特定钩子处理文件的流向和位置
wenpack配置分三个文件:
webpack.base.js 公共配置,所有环境都一样
webapck.dev.js 开发环境特有配置
webpack.pro.js 打包特有配置,包括打包到test,production这两个环境
在package.json加三个命令行
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --config ./webpack.dev.js",
"build": "cross-env NODE_ENV=production webpack --config ./webpack.pro.js",
"build-test": "cross-env NODE_ENV=test webpack --config ./webpack.pro.js"
},
执行命令
yarn dev 或者 npm run dev启动开发环境
yarn build 或者 npm run build打包到生产环境也就是production环境
yarn build-test 或者 npm run build-test打包到测试环境
看到这里你会发现我用NODE_ENV这个变量来区分各个环境的
同时还要在webpack.base.js配置webpack.DefinePlugin把变量注入进去
plugins: [
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify(process.env.NODE_ENV) // 提取package.json中的NODE_ENV变量注入webpack区分开发、测试、生产环境
}
})
]
然后在代码中可通过process.env.NODE_ENV来判断,如每个环境api的前缀不一样
let baseurl
const env = process.env.NODE_ENV
console.log(env)
if (env === 'development') {
// 开发环境
baseurl = 'http://a.com'
} else if (env === 'test') {
//测试环境
baseurl = 'http://b.com'
} else {
// 生产环境
baseurl = 'http://c.com'
}
配置多页面
多页面其实就是多个入口,多出口,想明白这点也就简单了,先看目录结构src/pages下面有两个目录。download,register这两个页面的源码、资源都在自己的目录里面

然后webpack.base.js配置两个入口,一个download一个register
entry: {
download: './src/pages/download/index.js',
register: './src/pages/register/index.js'
},
和配置一个插件 html-webpack-plugin
plugins: [
new HtmlWebpackPlugin({
template: 'src/pages/download/index.html',
filename: 'download.html',
chunks: ['download'] // 提取注入html的js文件
}),
new HtmlWebpackPlugin({
template: 'src/pages/register/index.html',
filename: 'register.html',
chunks: ['register'] // // 提取注入html的js文件
}),
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify(process.env.NODE_ENV) // 提取package.json中的NODE_ENV变量注入webpack区分开发、测试、生产环境
}
})
]
其中主要是 配置 chunks: ['register']这里,因为打包的时候会生成register.js和download.js,如果你不指定chunks的话,所有的js都会注入到html模板里面去,我们的需求是register.html只要register.js而download.html只要download.js
这样就配置多页面成功了!
其他常规配置:
打包时es6转es5
scss处理:开发时配置与打包配置不一样
图片处理
js,css压缩处理
代码贴出来在下面让大家参考一下
webpack.base.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const webpack = require('webpack')
module.exports = {
entry: {
download: './src/pages/download/index.js',
register: './src/pages/register/index.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [// presets使用于一般的业务项目中,不适于库、框架的研发项目,因为babel-polyfill会污染全局
[
"@babel/preset-env",
{
"useBuiltIns": "usage", // 只加入用到的es6新特性
"corejs": 2
}
]
]
}
},
{
test: /\.(jpe?g|png|gif)$/,
use: {
loader: 'url-loader', // 默认直接生成base64
options: {
name: '[name].[hash:5].[ext]',
outputPath: 'img/',
limit: 4 * 1024
}
}
},
{
test: /\.(eot|ttf|svg)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[hash:5].[ext]',
outputPath: 'font/'
}
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/pages/download/index.html',
filename: 'download.html',
chunks: ['download'] // 提取注入html的js文件
}),
new HtmlWebpackPlugin({
template: 'src/pages/register/index.html',
filename: 'register.html',
chunks: ['register']
}),
new CleanWebpackPlugin(), // 清除dist目录
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify(process.env.NODE_ENV) // 提取package.json中的NODE_ENV变量注入webpack区分开发、测试、生产环境
}
})
],
resolve: {
extensions: ['.js'], // 省略.js
alias: {
'@': path.resolve(__dirname, 'src')
}
}
}
webpack.dev.js
const path = require('path')
const baseConfig = require('./webpack.base')
const merge = require('webpack-merge')
const devConfig = {
mode: 'development',
devtool: 'cheap-module-eval-source-map', // 开发环境
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
'postcss-loader'
]
}
]
},
}
module.exports = merge(baseConfig, devConfig)
webpack.pro.js
const baseConfig = require('./webpack.base')
const path = require('path')
const merge = require('webpack-merge')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const TerserJSPlugin = require('terser-webpack-plugin')
const proConfig = {
mode: 'production',
devtool: 'none', // 或者cheap-module-source-map
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js', // 入口文件名
chunkFilename: '[name].[contenthash].js', // 入口文件引入的其他模块
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
chunkFilename: '[id].[contenthash].css'
}) // css提取分割
],
optimization: {
minimizer: [
new TerserJSPlugin({}),
new OptimizeCSSAssetsPlugin({})
]
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: false
}
},
'css-loader',
'postcss-loader'
]
},
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: false
}
},
'css-loader',
'sass-loader',
'postcss-loader'
]
}
]
}
}
module.exports = merge(baseConfig, proConfig)
其中还有postcss用来配置兼容不同浏览器css的配置
postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]
}
package.json
{
"name": "yihuo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --config ./webpack.dev.js",
"build": "cross-env NODE_ENV=production webpack --config ./webpack.pro.js",
"build-test": "cross-env NODE_ENV=test webpack --config ./webpack.pro.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.6.4",
"@babel/preset-env": "^7.6.3",
"autoprefixer": "^9.6.4",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"core-js": "2",
"cross-env": "^5.2.1",
"css-loader": "^3.2.0",
"file-loader": "^5.1.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.0",
"url-loader": "^2.2.0",
"webpack": "^4.41.0",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.2",
"webpack-merge": "^4.2.2"
}
}
其他项目配置优化如
resolve配置
loader配置include\exclude
treeshaking
多进程打包 thread-loader parallel-loader happypack
cache-loader
dll-plugin
splitChunk按需加载等
这里只在webpack.base.js用了resolve配置,杀鸡不用牛刀。
总结
又巩固了一下webpack!
网友评论