美文网首页
webpack配置多页面实践

webpack配置多页面实践

作者: 0月 | 来源:发表于2020-03-11 20:07 被阅读0次

    需求

    最近公司又开发一个app,本来没我前端啥事的,需求评审都没我份,我也懒得参加,可是开发到半路,需求改来改去后,还是要前端写两个h5页面配合一下。一个h5邀请注册页面,一个app下载页面,页面很简单,活不多,用框架又增加打包体积,想来想去还是亲手用原生js和配置webpack来搞定它吧,考验脱离框架、库开发出精简业务代码的时候到了。

    为什么要用webpack?
    理由:

    1. 为了项目可持续化、可维护、可扩展等也就是我们经常说的前端工程化。webpack可以说是前端工程化进程的产物了,里面种种好处不一一列举,以前那种手写html\css\js的年代一去不复返了,那种弊端太多了。
    2. 闲的没事干&&巩固一下webpack知识。

    设计稿

    注册.png
    下载.png

    架构

    webpack多页面配置,js语法es6,样式预处理器scss。
    环境要区分development,test,production三个环境。其中development是我们启动webpack-dev-server开发的环境,test是打包到测试环境,production是打包到线上环境,因为注册页面有两个接口,一个发送验证码,一个注册接口。

    webpack基本配置概念:

    entry配置入口文件js,
    output配置出口,
    loader处理各种文件格式转换,
    plugin在特定钩子处理文件的流向和位置

    wenpack配置分三个文件:
    webpack.base.js 公共配置,所有环境都一样
    webapck.dev.js 开发环境特有配置
    webpack.pro.js 打包特有配置,包括打包到test,production这两个环境
    在package.json加三个命令行

    "scripts": {
        "dev": "cross-env NODE_ENV=development webpack-dev-server --config ./webpack.dev.js",
        "build": "cross-env NODE_ENV=production webpack --config ./webpack.pro.js",
        "build-test": "cross-env NODE_ENV=test webpack --config ./webpack.pro.js"
      },
    

    执行命令
    yarn dev 或者 npm run dev启动开发环境
    yarn build 或者 npm run build打包到生产环境也就是production环境
    yarn build-test 或者 npm run build-test打包到测试环境

    看到这里你会发现我用NODE_ENV这个变量来区分各个环境的
    同时还要在webpack.base.js配置webpack.DefinePlugin把变量注入进去

    plugins: [
    new webpack.DefinePlugin({
          "process.env": {
            NODE_ENV: JSON.stringify(process.env.NODE_ENV) // 提取package.json中的NODE_ENV变量注入webpack区分开发、测试、生产环境
          }
        })
    ]
    
    

    然后在代码中可通过process.env.NODE_ENV来判断,如每个环境api的前缀不一样

    let baseurl 
    const env = process.env.NODE_ENV
    console.log(env)
    if (env === 'development') {
    // 开发环境
    baseurl  = 'http://a.com'
    } else if (env === 'test') {
    //测试环境
    baseurl  = 'http://b.com'
     } else {
    // 生产环境
    baseurl  = 'http://c.com'
     }
    

    配置多页面

    多页面其实就是多个入口,多出口,想明白这点也就简单了,先看目录结构src/pages下面有两个目录。download,register这两个页面的源码、资源都在自己的目录里面

    目录结构.png

    然后webpack.base.js配置两个入口,一个download一个register

    entry: {
        download: './src/pages/download/index.js',
        register: './src/pages/register/index.js'
      },
    

    和配置一个插件 html-webpack-plugin

    plugins: [
        new HtmlWebpackPlugin({
          template: 'src/pages/download/index.html',
          filename: 'download.html',
          chunks: ['download'] // 提取注入html的js文件
        }),
       new HtmlWebpackPlugin({
          template: 'src/pages/register/index.html',
          filename: 'register.html',
          chunks: ['register'] // // 提取注入html的js文件
        }),
      new webpack.DefinePlugin({
          "process.env": {
            NODE_ENV: JSON.stringify(process.env.NODE_ENV) // 提取package.json中的NODE_ENV变量注入webpack区分开发、测试、生产环境
          }
        })
    ]
    

    其中主要是 配置 chunks: ['register']这里,因为打包的时候会生成register.js和download.js,如果你不指定chunks的话,所有的js都会注入到html模板里面去,我们的需求是register.html只要register.js而download.html只要download.js
    这样就配置多页面成功了!

    其他常规配置:
    打包时es6转es5
    scss处理:开发时配置与打包配置不一样
    图片处理
    js,css压缩处理
    代码贴出来在下面让大家参考一下
    webpack.base.js

    const path = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const { CleanWebpackPlugin } = require('clean-webpack-plugin')
    const webpack = require('webpack')
    
    module.exports = {
     entry: {
       download: './src/pages/download/index.js',
       register: './src/pages/register/index.js'
     },
     module: {
       rules: [
         {
           test: /\.js$/,
           exclude: /node_modules/,
           loader: 'babel-loader',
           options: {
             presets: [// presets使用于一般的业务项目中,不适于库、框架的研发项目,因为babel-polyfill会污染全局
               [
                 "@babel/preset-env",
                 {
                   "useBuiltIns": "usage", // 只加入用到的es6新特性
                   "corejs": 2
                 }
               ]
             ]
           }
         },
         {
           test: /\.(jpe?g|png|gif)$/,
           use: {
             loader: 'url-loader', // 默认直接生成base64
             options: {
               name: '[name].[hash:5].[ext]',
               outputPath: 'img/',
               limit: 4 * 1024
             }
           }
         },
         {
           test: /\.(eot|ttf|svg)$/,
           use: {
             loader: 'file-loader',
             options: {
               name: '[name].[hash:5].[ext]',
               outputPath: 'font/'
             }
           }
         }
       ]
     },
     plugins: [
       new HtmlWebpackPlugin({
         template: 'src/pages/download/index.html',
         filename: 'download.html',
         chunks: ['download'] // 提取注入html的js文件
       }),
       new HtmlWebpackPlugin({
         template: 'src/pages/register/index.html',
         filename: 'register.html',
         chunks: ['register']
       }),
       new CleanWebpackPlugin(), // 清除dist目录
       new webpack.DefinePlugin({
         "process.env": {
           NODE_ENV: JSON.stringify(process.env.NODE_ENV) // 提取package.json中的NODE_ENV变量注入webpack区分开发、测试、生产环境
         }
       })
     ],
     resolve: {
       extensions: ['.js'], // 省略.js
       alias: {
         '@': path.resolve(__dirname, 'src')
       }
     }
    }
    
    

    webpack.dev.js

    const path = require('path')
    const baseConfig = require('./webpack.base')
    const merge = require('webpack-merge')
    
    const devConfig = {
      mode: 'development',
      devtool: 'cheap-module-eval-source-map', // 开发环境
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
      },
      module: {
        rules: [
          {
            test: /\.css$/,
            use: ['style-loader', 'css-loader', 'postcss-loader']
          },
          {
            test: /\.scss$/,
            use: [
              'style-loader',
              'css-loader',
              'sass-loader',
              'postcss-loader'
            ]
          }
        ]
      },
    }
    
    module.exports = merge(baseConfig, devConfig)
    
    

    webpack.pro.js

    const baseConfig = require('./webpack.base')
    const path = require('path')
    const merge = require('webpack-merge')
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
    const TerserJSPlugin = require('terser-webpack-plugin')
    
    const proConfig = {
      mode: 'production',
      devtool: 'none', // 或者cheap-module-source-map
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].[contenthash].js', // 入口文件名
        chunkFilename: '[name].[contenthash].js', // 入口文件引入的其他模块
      },
      plugins: [
        new MiniCssExtractPlugin({
          filename: '[name].[contenthash].css',
          chunkFilename: '[id].[contenthash].css'
        }) // css提取分割
      ],
      optimization: {
        minimizer: [
          new TerserJSPlugin({}),
          new OptimizeCSSAssetsPlugin({})
        ]
      },
      module: {
        rules: [
          {
            test: /\.css$/,
            use: [
              {
                loader: MiniCssExtractPlugin.loader,
                options: {
                  hmr: false
                }
              },
              'css-loader',
              'postcss-loader'
            ]
          },
          {
            test: /\.scss$/,
            use: [
              {
                loader: MiniCssExtractPlugin.loader,
                options: {
                  hmr: false
                }
              },
              'css-loader',
              'sass-loader',
              'postcss-loader'
            ]
          }
        ]
      }
    }
    
    module.exports = merge(baseConfig, proConfig)
    
    

    其中还有postcss用来配置兼容不同浏览器css的配置
    postcss.config.js

    module.exports = {
      plugins: [
        require('autoprefixer')
      ]
    }
    

    package.json

    {
      "name": "yihuo",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "dev": "cross-env NODE_ENV=development webpack-dev-server --config ./webpack.dev.js",
        "build": "cross-env NODE_ENV=production webpack --config ./webpack.pro.js",
        "build-test": "cross-env NODE_ENV=test webpack --config ./webpack.pro.js"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "@babel/core": "^7.6.4",
        "@babel/preset-env": "^7.6.3",
        "autoprefixer": "^9.6.4",
        "babel-loader": "^8.0.6",
        "clean-webpack-plugin": "^3.0.0",
        "core-js": "2",
        "cross-env": "^5.2.1",
        "css-loader": "^3.2.0",
        "file-loader": "^5.1.0",
        "html-webpack-plugin": "^3.2.0",
        "mini-css-extract-plugin": "^0.8.0",
        "node-sass": "^4.12.0",
        "optimize-css-assets-webpack-plugin": "^5.0.3",
        "postcss-loader": "^3.0.0",
        "sass-loader": "^8.0.0",
        "style-loader": "^1.0.0",
        "url-loader": "^2.2.0",
        "webpack": "^4.41.0",
        "webpack-cli": "^3.3.9",
        "webpack-dev-server": "^3.8.2",
        "webpack-merge": "^4.2.2"
      }
    }
    

    其他项目配置优化如
    resolve配置
    loader配置include\exclude
    treeshaking
    多进程打包 thread-loader parallel-loader happypack
    cache-loader
    dll-plugin
    splitChunk按需加载等

    这里只在webpack.base.js用了resolve配置,杀鸡不用牛刀。

    总结

    又巩固了一下webpack!

    相关文章

      网友评论

          本文标题:webpack配置多页面实践

          本文链接:https://www.haomeiwen.com/subject/tllhjhtx.html