教你用webpack4打造優化到極致的活動頁面

前言

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

配置loader選項

  • css樣式處理:安裝postcss-loader,less, less-loader,css-loader,style-loader並添加配置
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')
  ]
}
複製代碼
  • 圖片文件處理:安裝html-loader,url-loader,file-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/'
        }
    }]
}
複製代碼
  • es6+處理:安裝@babel/core, @babel/core, @babel/polyfill,@babel/preset-env, babel-loader並添加配置
{
    test: /\.js$/,
    exclude: /node_modules/,
    loader: 'babel-loader'
}
複製代碼

新建一個.babelrc到根目錄es6

{
    "presets": [
    	[
            "@babel/preset-env",
            {
                "useBuiltIns": "usage"
            }
    	]
    ]
}
複製代碼

Plugins 的安裝

咱們先安裝如下插件github

  • HtmlWebpackPlugin():根據html模板,將css,js打包生成對應的html中
  • CleanWebpackPlugin():清除上次打包的文件
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目錄生成對應的文件

【重點】項目優化

分開配置webpack.config.js文件,便於咱們後期操做,安裝webpack-merge

  • webpack.base.js 生產環境和開發環境公用代碼,配置以下:
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

  • webpack.dev.js 開發環境,配置以下:
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)
複製代碼
  • webpack.prod.js 生產環境,配置以下:
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)
複製代碼
  • 最後改下package.json配置
"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代理配置項
    }
},
複製代碼

生產環境優化

  • 安裝如下插件並使用: mini-css-extract-plugin(分離樣式),optimize-css-assets-webpack-plugin(壓縮css), uglifyjs-webpack-plugin(壓縮js)雖然生產環境會自動壓縮js,但使用插件有更多的選擇項
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;
    }
})
複製代碼

tree-shaking

咱們知道打包存在es6語法文件時會很大,是由於webpack會默認把全部新js語法打包進去,而@babel/polyfill,會把只用到的新js語法打包進去,具體配置在.babelrc改成"useBuiltIns": "usage"

圖片壓縮和使用base64編碼

安裝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看看

相關文章
相關標籤/搜索