通常待過大公司的同窗都知道,一個成熟穩定的公司確定須要銷售產品或推廣產品來盈利,推廣本身的產品則須要活動頁面來引流。下面,我將分享本身在公司的探索經歷,教你用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
複製代碼
圖中可見生成dist目錄,dist目錄生成對應的文件
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看看