通常待过大公司的同窗都知道,一个成熟稳定的公司确定须要销售产品或推广产品来盈利,推广本身的产品则须要活动页面来引流。下面,我将分享本身在公司的探索经历,教你用webpack4打造优化到极致的活动页面。css
spcial为项目名称,build为webpack配置,common为公用文件,dist为打包后的文件(这里就是要上线的活动页面),src就是对应日期所作的活动页面html
安装webpack webpack-cli,配置webpack.config.js.node
npm init
npm i webpack webpack-cli -S
+ webpack-cli@3.3.4
+ webpack@4.35.0
复制代码
webpack.config.js:webpack
const path = require('path');
module.exports = {
entry: {
main: 'src/20190601/index.js'
},
module: {
rules: [
{
}
]
},
output: {
path: path.resolve(__dirname,'./dist/20190601'),
filename: 'index.js',
chunkFilename: '[name].js' // 代码拆分后的文件名
}
}
复制代码
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders:2, //防止样式嵌套css失效
}
},
'less-loader',
'postcss-loader'
]
},
]
复制代码
固然,要使用postcss-loader须要额外的配置安装autoprefixer:npm i autoprefixer -D
, 在special根目录增长文件postcss.config.jsgit
module.exports = {
plugins: [
require('autoprefixer')
]
}
复制代码
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: ['file-loader']
},
{
test: /\.(html)$/,
use: {
loader: 'html-loader',
options: {
attrs: ['img:src', 'img:data-src', 'audio:src','title'],
//minimize: true
}
}
},
{
test: /\.(jpg|png|gif|webp)$/,
use: [{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
}]
}
复制代码
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
复制代码
新建一个.babelrc到根目录es6
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage"
}
]
]
}
复制代码
咱们先安装如下插件github
npm i clean-webpack-plugin html-webpack-plugin -D
webpack.config.js新增配置
import HtmlWebpackPlugin from 'html-webpack-plugin'
import {CleanWebpackPlugin} from 'clean-webpack-plugin' //clean-webpack-plugin版本>=3.0.0写法
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: 'src/20190601/index.html'
})
],
复制代码
我本身新建一个活动,而后测试web
npm run webpack --mode production
复制代码
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const Config = {
entry: {
main: ''
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: ['file-loader']
},
{
test: /\.(html)$/,
use: {
loader: 'html-loader',
options: {
attrs: ['img:src', 'img:data-src', 'audio:src','title'],
//minimize: true
}
}
},
{
test: /\.(jpg|png|gif|webp)$/,
use: [{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
}]
}
]
},
plugins: [
new CleanWebpackPlugin()
],
output: {
}
}
function setDate(date) {
Config.entry.main = `./src/${date}/index.js`;
Config.plugins.push(new HtmlWebpackPlugin({
template: `src/${date}/index.html`,
// minify: true
}));
Config.output = {
path: path.resolve(__dirname,'../dist/'+date),
filename: 'index.js',
chunkFilename: '[name].js' // 代码拆分后的文件名
}
}
setDate('20190614')
module.exports = Config;
复制代码
这里把某些配置提出来是由于每一个活动页面名称不一样,打包的时候改变setDate()便可npm
const merge = require('webpack-merge');
const Config = require('./webpack.base.js');
const devConfig = {
mode: 'development',
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders:2,
}
},
'less-loader',
'postcss-loader'
]
},
]
}
}
module.exports = merge(Config,devConfig)
复制代码
const merge = require('webpack-merge');
const Config = require('./webpack.base.js')
const prodConfig = {
mode: 'production',
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader'
'css-loader',
'postcss-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader'
{
loader: 'css-loader',
options: {
importLoaders:2,
}
},
'less-loader',
'postcss-loader'
]
},
]
}
}
Config.output.publicPath = '20190614/'; //挂载到服务器路径
module.exports = merge(Config,prodConfig)
复制代码
"scripts": {
"build": "webpack --config ./build/webpack.prod.js",
"dev": "webpack-dev-server --config ./build/webpack.dev.js"
},
复制代码
安装webpack-dev-server,并在webpack.dev.js添加配置json
npm i webpack-dev-server -D
devServer: {
contentBase: './dist',
port: 8088,
proxy: {
//api代理配置项
}
},
复制代码
npm i mini-css-extract-plugin optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin -D
复制代码
webpack.prod.js配置以下:
const merge = require('webpack-merge');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const Config = require('./webpack.base.js')
const prodConfig = {
mode: 'production',
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders:2,
}
},
'less-loader',
'postcss-loader'
]
},
]
},
optimization: {
minimizer: [
new OptimizeCSSAssetsPlugin({}),
new UglifyJsPlugin()
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[name].chunk.css'
})
]
}
Config.output.publicPath = '20190614/'; //挂载到服务器路径
module.exports = merge(Config,prodConfig)
复制代码
代码分割的做用将第三方的插件分割成单独文件,减小index.js体积,减小白屏时间,好比我页面中用到swiper, 那我能够把它分割成一个单独js,webpack.prod.js增长配置以下
optimization: {
minimizer: [
new OptimizeCSSAssetsPlugin({}),
new UglifyJsPlugin()
],
splitChunks: {
chunks: 'initial', //initial表明只分割同步代码,async分割异步代码,all分割所有第三方代码
minSize: 30000, //大约30kb才能分割
minChunks: 1,
name: true,
cacheGroups: {
swiper: {
name: 'swiper',
test: /[\\/]node_modules[\\/]swiper[\\/]/,
priority: 10
},
vendors: {
name: 'orthers',
test: /[\\/]node_modules[\\/]/,
priority: -10
},
}
}
},
复制代码
js异步加载对于单屏的活动页面很是重要,大量减小首批渲染时间,以swiper为例: 安装babel-plugin-transform-dynamic-import-default,由于js异步引入语法import()属于实验性语法
npm i babel-plugin-transform-dynamic-import-default -D
复制代码
在.babelrc配置
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage"
}
]
],
"plugins": ["babel-plugin-transform-dynamic-import-default"]
}
复制代码
实战引用:
var flag = true;
document.addEventListener('scroll',() => {
if(flag) {
import(/* webpackPrefetch: true */ 'swiper').then( ()=> {
console.log("引入成功")
var swiper1 = new Swiper('.swiper-container',{
loop: true,
pagination:'.swiper-pagination',
autoplay: 3000,
speed:1000
});
})
flag = false;
}
})
复制代码
咱们知道打包存在es6语法文件时会很大,是由于webpack会默认把全部新js语法打包进去,而@babel/polyfill,会把只用到的新js语法打包进去,具体配置在.babelrc改成"useBuiltIns": "usage"
安装image-webpack-loader
{
test: /\.(jpg|png|gif|webp)$/,
use: [{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048 //小于2k的图片变成base64编码,减小http请求
}
},{
loader: 'image-webpack-loader', //图片过大时修改此配置进行压缩
options: {
mozjpeg: {
progressive: true,
quality: 100
},
pngquant: {
quality: 90,
speed: 4
},
gifsicle: {
interlaced: false,
}
}
}]
}
复制代码
当时想着用webpack来管理活动页面主要是由于提升开发效率和提升产品质量,经测试,同一个活动页面,一个用webpack打包,一个用普通html写,首屏渲染时间至少减小2倍,网速慢状况下性能更突出。 项目已放上github,欢迎同窗们去star学习:去github看看