webpack配置多页面实践

需求

最近公司又开发一个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!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容