本文介绍如何使用webpack和babel打包基于jQuery的多页Web项目。重点讲解如何通过配置多个入口文件实现模块分割加载,解决单文件过大问题。针对多页面场景,详细阐述将CSS单独打包为JS模块以处理图片Base64转换导致体积增大的策略,以及利用HtmlWebpackPlugin和CopyWebpackPlugin生成多HTML页面和静态资源的具体配置方法。
项目背景与打包方案
尽管当前已是2019年,部分项目仍依赖jQuery。为了解决jQuery带来的兼容性问题,并顺利使用ES6语法进行开发,本文探讨利用webpack配合babel进行代码打包发布的方案。
实现该方案需关注以下几个关键点:
多入口与CSS处理策略
1.为了将模块分割加载,不至于一个js文件过大,一个页面中使用多个js文件 2.由于是多页项目(多个html),每个页面使用的js文件都不一致 基于以上两点,需要配置多个入口文件 3.会把小图片转换成base64,所以可能css转成的js文件会比较大,所以css文件都单独设置入口js
多页面配置示例
假设项目包含三个页面:index、share和assist。
这三个页面共用一个CSS文件:common.css。
在设置入口文件时,可以参考如下配置方式。
entry: {
// 通用css
commoncss: path.resolve(__dirname, './src/css/common.css.js'),
// 主页
indexcss: path.resolve(__dirname, './src/css/index.css.js'),
index: path.resolve(__dirname, './src/index.js'),
// 页1
sharecss: path.resolve(__dirname, './src/css/share.css.js'),
share: path.resolve(__dirname, './src/share.js'),
// 页2
assistcss: path.resolve(__dirname, './src/css/assist.css.js'),
assist: path.resolve(__dirname, './src/assist.js'),
}
其中,common.css.js文件仅包含少量代码。
import '../css/base.css';
import '../css/plugin.css';
import '../css/common.css';
common.css.js文件的内容到此结束。
由于包含部分图片的Base64编码,该文件体积约为100+KB。
类似地,还存在index.css.js、share.css.js和assist.css.js文件。其中index.css.js的配置如下。
import '../css/index.css';
是的,仅有一行代码。
打包后生成的JS文件大小取决于引入的小图片数量,通常在几百KB左右。
关键插件配置
接下来,需要引入三个webpack插件。
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const jquery = require('jquery');
HtmlWebpackPlugin用于打包生成多个HTML文件。
CopyWebpackPlugin用于处理img标签引用的图片,具体用法稍后说明。
jQuery作为全局引用库直接引入。
webpack.config.js中的plugins配置如下所示。
plugins: [
new webpack.ProvidePlugin({
$:"jquery"
}),
new CopyWebpackPlugin([{
from: __dirname + '/src/public/'
}]), // 吧src下public文件夹下的所有内容直接拷贝到dist(输出目录)下
new HtmlWebpackPlugin({
filename: 'index.htm',
template: 'src/index.html',
chunks: ['commoncss', 'indexcss', 'index'],
inject: 'true',
hash: true,
}),
new HtmlWebpackPlugin({
filename: 'share.htm',
template: 'src/share.html',
chunks: ['commoncss', 'sharecss', 'share'],
inject: 'true',
hash: true,
}),
new HtmlWebpackPlugin({
filename: 'assist.htm',
template: 'src/assist.html',
chunks: ['commoncss', 'assistcss', 'assist'],
inject: 'true',
hash: true,
})
]
目录结构与输出说明
src目录下的文件结构如下。

index.js、assist.js和share.js分别是三个页面的入口文件。
index.html、assist.html和share.html是三个页面的模板,HTML代码可以直接编写在此处(当然,如果使用模板文件也是可行的,只要HtmlWebpackPlugin插件支持即可)。
dist文件夹的输出结构如下。

注意输出文件后缀为.htm而非.html,这是为了便于读者区分模板文件和最终输出的文件。
我们知道,webpack打包过程不会处理HtmlWebpackPlugin中template里img标签引用的图片。因此,所有在HTML中使用img标签引用的图片都必须放置在public文件夹下,CopyWebpackPlugin组件会直接将图片复制到输出目录。
关于HtmlWebpackPlugin的具体参数细则,网上已有大量相关资料可供查阅。至于loader、babel等其他配置并非本文重点,在此不再赘述。
最后,附上完整的webpack.config.js文件内容。
let actName = 'yourProjectName';//
let actKV = {
name: actName,
entry: {
// 通用css
commoncss: path.resolve(__dirname, './src/css/common.css.js'),
// 主页
indexcss: path.resolve(__dirname, './src/css/index.css.js'),
index: path.resolve(__dirname, './src/index.js'),
// 分享页1
sharecss: path.resolve(__dirname, './src/css/share.css.js'),
share: path.resolve(__dirname, './src/share.js'),
// 分享页2
assistcss: path.resolve(__dirname, './src/css/assist.css.js'),
assist: path.resolve(__dirname, './src/assist.js'),
}
};
return {
entry: actKV.entry,
target: "web",
output: {
path: path.resolve(__dirname + '/dist/'+actName),
// publicPath: '.\\',
filename: 'js/[name].js',
// chunkFilename: "[name].chunk.[hash].js",
},
plugins: [
new webpack.ProvidePlugin({
$:"jquery"
}),
new CopyWebpackPlugin([{
from: __dirname + '/src/public/'
}]),
new HtmlWebpackPlugin({
filename: 'index.htm',
template: 'src/index.html',
chunks: ['commoncss', 'indexcss', 'index'],
inject: 'true',
hash: true,
}),
new HtmlWebpackPlugin({
filename: 'share.htm',
template: 'src/share.html',
chunks: ['commoncss', 'sharecss', 'share'],
inject: 'true',
hash: true,
}),
new HtmlWebpackPlugin({
filename: 'assist.htm',
template: 'src/assist.html',
chunks: ['commoncss', 'assistcss', 'assist'],
inject: 'true',
hash: true,
})
],
mode: 'development',
node: {
__filename: true,
__dirname: true
},
devtool: isProduction ? 'source-map':'inline-source-map',
devServer:{
inline: true,
open: true,
historyApiFallback: true,
// host: ip.address(),
host: 'localhost',
progress: true,
contentBase: "./dist/",
port: 3430,
historyApiFallback:true,
publicPath:'/src/',
proxy: {
'*': {
target: 'http://127.0.0.1:3430',
secure: false
}
},
},
resolve: {
alias: {
},
extensions: ['.js', '.less', '.css', '.vue', '.jsx'],
},
externals: {
},
module: {
rules: [{
test: /\.vue$/,
loader: 'vue-loader',
}, {
test: /\.js$/,
include: path.join(__dirname,'/src'),
exclude: path.resolve(__dirname, 'node_modules'),
use:[
{
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}
]
}, {
test: /\.xml$/,
loader: "xml-loader"
}, {
test: /\.(css|less)$/,
loader: "style-loader!css-loader",
},
{
test: /\.(png|jpg|jpeg|gif|icon|webp)$/,
loader: 'url-loader',
options: {
limit: 16384,
name: 'images/[name].[hash:5].[ext]',
}
},
{
test: /\.(woff|woff2|svg|eot|ttf)\??.*$/,
loader: "file-loader?&name=assets/fonts/[name].[ext]"
}, {
test: /\.txt$/,
loader: "text-loader"
},{
test: /\.jsx$/,
exclude: /node_modules/,
loaders: ['jsx-loader', 'babel-loader']
}]
},
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。