本文记录简单的webpack接入流程,不涉及深入的性能优化。本文基于webpack5进行构建。
首先在项目的根目录创建package.json文件,可以通过npm init进行初始化创建。
第一步,区分环境进行分别配置
在根目录下创建webpack.base.js,webpack.dev.js,webpack.prod.js三个文件。
通用的配置放在webpack.base.js中,在另外两个文件通过webpack-merge插件进行配置项的merge。
webpack.dev.js的配置
const path = require('path');
const {merge} = require('webpack-merge');
const common = require('./webpack.base.js');
module.exports = merge(common,{
mode: "development",
devtool: 'inline-source-map',
});
webpack.prod.js的配置
const path = require('path');
const {merge} = require('webpack-merge');
const common = require('./webpack.config.js');
const Webpack5QCDNFile = require('@q/webpack5-qcdn-file');
module.exports = merge(common,{
mode: "production",
plugins: [
new Webpack5QCDNFile({
qcdnOpt: {
https: true,
image: {
https: true,
domains: [
"so1.xxx.com",
"so2.xxx.com",
"so3.xxx.com",
"so4.xxx.com",
"so5.xxx.com",
]
},
static: {
domains: [
"ss1.xxx.com",
"ss2.xxx.com",
"ss3.xxx.com",
"ss4.xxx.com",
"ss5.xxx.com",
],
}
},
resPath: path.resolve(__dirname, "dist")
})
]
});
接下来配置package.json中的scripts:
......
"scripts": {
"dev": "webpack --watch --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
}
......
第二步,配置webpack.base.js
项目中最基本的需求是JS和CSS文件的编译打包处理。
首先配置入口文件和输出的文件及路径
const distPath = path.join(__dirname, "dist");
module.exports = {
entry: './assets/common/base.js',
output: {
filename: 'js/[name].bundle.js',
path: distPath,
},
}
在base.js文件中,可以把CSS和JS都放在这个文件中,webpack会根据配置进行处理。
// base.js的文件内容
import './reset.less';
import './common.less';
import $ from 'zepto';
$('.js-next-query').on('click',function(e){
//
});
接下来处理CSS和JS的编译
const distPath = path.join(__dirname, "dist");
const htmlTplPath = path.join(__dirname, "templates");
const htmlBuildPath = path.join(__dirname, "views");
module.exports = {
entry: './assets/common/base.js',
output: {
filename: 'js/[name].bundle.js',
path: distPath,
},
module: {
rules: [
{
// 模块规则(配置loader,解析器等选项)
test: /\.js$/i,
use: [{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: []
}
}],
exclude: /node_modules/,
},
{
test: /\.(less|css)$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('postcss-preset-env')({
browsers: 'last 4 versions',
})
]
}
}
},
'less-loader'
],
}
]
}
}
如果想把CSS也抽取成独立的文件,需要借助mini-css-extract-plugin插件
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const distPath = path.join(__dirname, "dist");
const htmlTplPath = path.join(__dirname, "templates");
const htmlBuildPath = path.join(__dirname, "views");
module.exports = {
entry: './assets/common/base.js',
output: {
filename: 'js/[name].bundle.js',
path: distPath,
},
module: {
rules: [
{
// 模块规则(配置loader,解析器等选项)
test: /\.js$/i,
use: [{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: []
}
}],
exclude: /node_modules/,
},
{
test: /\.(less|css)$/i,
use: [
'style-loader',
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('postcss-preset-env')({
browsers: 'last 4 versions',
})
]
}
}
},
'less-loader'
],
}
],
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].bundle.css"
}),
]
}
}
文件打包好之后需要引用的地方替换成最新的,可以借助html-webpack-plugin插件。
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const distPath = path.join(__dirname, "dist");
const htmlTplPath = path.join(__dirname, "templates");
const htmlBuildPath = path.join(__dirname, "views");
module.exports = {
entry: './assets/common/base.js',
output: {
filename: 'js/[name].bundle.js',
path: distPath,
},
module: {
rules: [
{
// 模块规则(配置loader,解析器等选项)
test: /\.js$/i,
use: [{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: []
}
}],
exclude: /node_modules/,
},
{
test: /\.(less|css)$/i,
use: [
'style-loader',
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('postcss-preset-env')({
browsers: 'last 4 versions',
})
]
}
}
},
'less-loader'
],
}
],
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].bundle.css"
}),
new HtmlWebpackPlugin({
filename: path.join(htmlBuildPath, 'index.html'), // 处理后的文件路径
template: path.join(htmlTplPath, `index.html`), // 待处理的文件路径
inject: 'body', // js文件在body的底部插入
minify: false // 是否开启html代码的压缩
}),
]
}
}
配置完后基本上就可以使用了
Zepto这类不支持import使用库的接入
zepto不支持common.js这样在使用时就不能使用import的形式。可以通过exports-loader和script-loader插件解决。
需要再webpack配置的rules中处理:
{
test: require.resolve('zepto'),
use: [
'exports-loader?window.Zepto',
'script-loader'
]
}
完整的配置如下:
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const distPath = path.join(__dirname, "dist");
const htmlTplPath = path.join(__dirname, "templates");
const htmlBuildPath = path.join(__dirname, "views");
module.exports = {
entry: './assets/common/base.js',
output: {
filename: 'js/[name].bundle.js',
path: distPath,
},
module: {
rules: [
{
// 模块规则(配置loader,解析器等选项)
test: /\.js$/i,
use: [{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: []
}
}],
exclude: /node_modules/,
},
{
test: /\.(less|css)$/i,
use: [
'style-loader',
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('postcss-preset-env')({
browsers: 'last 4 versions',
})
]
}
}
},
'less-loader'
],
},
{
test: require.resolve('zepto'),
use: [
'exports-loader?window.Zepto',
'script-loader'
]
}
],
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].bundle.css"
}),
new HtmlWebpackPlugin({
filename: path.join(htmlBuildPath, 'index.html'), // 处理后的文件路径
template: path.join(htmlTplPath, `index.html`), // 待处理的文件路径
inject: 'body', // js文件在body的底部插入
minify: false // 是否开启html代码的压缩
}),
]
}
}
代码中使用了zepto这个脚本库,在生产环境通常直接使用zepto的cdn地址,文件打包时就需要将zepto排除。可以在webpack的配置文件中配置
externals: {
zepto: 'Zepto'
}
最终版完整的代码:
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const distPath = path.join(__dirname, "dist");
const htmlTplPath = path.join(__dirname, "templates");
const htmlBuildPath = path.join(__dirname, "views");
module.exports = {
entry: './assets/common/base.js',
output: {
filename: 'js/[name].bundle.js',
path: distPath,
},
module: {
rules: [
{
// 模块规则(配置loader,解析器等选项)
test: /\.js$/i,
use: [{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: []
}
}],
exclude: /node_modules/,
},
{
test: /\.(less|css)$/i,
use: [
'style-loader',
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('postcss-preset-env')({
browsers: 'last 4 versions',
})
]
}
}
},
'less-loader'
],
},
{
test: require.resolve('zepto'),
use: [
'exports-loader?window.Zepto',
'script-loader'
]
}
],
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].bundle.css"
}),
new HtmlWebpackPlugin({
filename: path.join(htmlBuildPath, 'index.html'), // 处理后的文件路径
template: path.join(htmlTplPath, `index.html`), // 待处理的文件路径
inject: 'body', // js文件在body的底部插入
minify: false // 是否开启html代码的压缩
}),
],
externals: {
zepto: 'Zepto'
}
}
}
package.json配置
{
"name": "test",
"version": "1.0.0",
"description": "test",
"main": "index.js",
"private": "true",
"scripts": {
"dev": "webpack --progress --profile --watch --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
},
"author": "xxx",
"license": "ISC",
"dependencies": {
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1"
},
"devDependencies": {
"@babel/core": "^7.21.0",
"@babel/preset-env": "^7.20.2",
"@q/webpack5-qcdn-file": "^1.0.0",
"babel-loader": "^9.1.2",
"css-loader": "^6.7.3",
"exports-loader": "^4.0.0",
"html-webpack-plugin": "^5.5.0",
"less": "^4.1.3",
"less-loader": "^11.1.0",
"mini-css-extract-plugin": "^2.7.2",
"postcss-loader": "^7.0.2",
"postcss-preset-env": "^8.0.1",
"script-loader": "^0.7.2",
"style-loader": "^3.3.1",
"webpack-merge": "^5.8.0",
"zepto": "^1.2.0",
}
}