webpack4系列教程(九):开发环境和生产环境

1. 构建开发环境

如果你一直跟随我前面的博文,那么你对webpack的基础知识已经有比较深刻的理解了。之前,我们一直执行着:

npm run build

来打包编译输出我们的代码,本文我们来看看如何构建一个开发环境,来使我们的开发变得方便些。

1.1 webpack-dev-server

webpack-dev-server是一个简单的小型的web服务器,并且能够实时重载,配置也很简单,首先安装:

npm install --save-dev webpack-dev-server

配置webpack.config.js:

devServer: {
    port: 8080,  // 端口号
    host: '0.0.0.0', // 主机名,设为该值可通过IP访问
    overlay: {
      errors: true // 错误提示
    }
  }

在package.json中添加命令:

    "dev": "cross-env NODE_ENV=development webpack-dev-server --config config/webpack.config.js"

执行:

npm run dev

可见我们的服务已经跑起来了:


Image 1.png

1.2 source-map

在webpack打包源码时,我们会很难找到错误的出现位置,比如将源文件 sum.js、minus.js打包到bundle.js中,其中一个源文件出现了错误,仅仅会追踪到bundle.js中,这对我们来说并不理想。因此为了更加便捷的找到错误的原始位置,JavaScript为我们提供了 source-map的功能,将编译后的代码映射回原始源代码。如果一个错误来自于 sum.js,source map 就会明确的告诉你。

我们来测试一下,在sum.js中输出一个错误:

// ES Mudule 规范
export default function (a, b) {
  console.error('this is test') // 输出错误
  return a + b
}

在没有devtool配置的情况下 npm run dev,会发现错误提示的行数并不准确,


Image 2.png

原因是我们的代码是被编译过的


Image 3.png

然后在webpack.config.js中加入配置:

  devtool: 'inline-source-map', // 加入devtool配置

当配置文件改动时需要重新执行 npm run dev:


Image 4.png
Image 5.png

错误提示行数以及源码映射都是正确的。devtool的取值有很多,大家可根据需要自行配置


Image 6.png

1.3 模块热替换

模块热替换(Hot Module Replacement)是 webpack 提供的最有用的功能之一。它允许在运行时更新各种模块,而无需进行完全刷新。

使用非常简单,在webpack.config.js中引入webpack:

  const webpack = require('webpack')

在plugins数组中添加:

  new webpack.NamedModulesPlugin(),
  new webpack.HotModuleReplacementPlugin()

给devServer中的hot属性设为true:

devServer: {
    port: 8080,  // 端口号
    host: '0.0.0.0', // 主机名,设为该值可通过IP访问
    overlay: {
      errors: true // 错误提示
    },
    hot: true
  }

这样我们修改代码的时候就可以局部刷新模块而不是刷新整个页面了。

2.构建生产环境

开发环境(development)和生产环境(production)的构建目标差异很大。在开发环境中,我们需要具有强大的、具有实时重新加载(live reloading)或热模块替换(hot module replacement)能力的 source map 和 localhost server。而在生产环境中,我们的目标则转向于关注更小的 bundle,更轻量的 source map,以及更优化的资源,以改善加载时间。由于要遵循逻辑分离,我们通常建议为每个环境编写彼此独立的 webpack 配置。

虽然,以上我们将生产环境和开发环境做了略微区分,但是,请注意,我们还是会遵循不重复原则(Don't repeat yourself - DRY),保留一个“通用”配置。为了将这些配置合并在一起,我们将使用一个名为 webpack-merge 的工具。通过“通用”配置,我们不必在环境特定的配置中重复代码。

我们先从安装 webpack-merge 开始,用来合并webpack配置项:

npm install --save-dev webpack-merge

在config文件夹下创建 webpack.dev.js 和 webpack.build.js 并修改 webpack.config.js,将开发与生产环境的公共配置放在webpack.config.js中:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

const isDev = process.env.NODE_ENV === 'development'

const config = {
  entry: {
    main: path.join(__dirname, '../src/main.js')
  },
  output: {
    filename: '[name].bundle.js',
    path: path.join(__dirname, '../dist')
  },
  module: {
    rules: [
      {
        test: /\.(vue|js|jsx)$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
        enforce: 'pre'
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: createVueLoaderOptions(isDev)
      },
      {
        test: /\.ejs$/,
        use: ['ejs-loader']
      },
      {
        test: /\.css$/,
        use: [
          isDev ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
          { loader: 'css-loader', options: { importLoaders: 1 } },
          'postcss-loader'
        ]
      },
      {
        test: /\.less$/,
        use: [
          isDev ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true
            }
          },
          'less-loader'
        ]
      },
      {
        test: /\.(jpg|jpeg|png|gif|svg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              name: '[path][name]-[hash:5].[ext]',
              limit: 1024
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, '../index.html'),
      inject: true,
      minify: {
        removeComments: true
      }
    })
  ]
}

module.exports = config

webpack.dev.js

const merge = require('webpack-merge')
const common = require('./webpack.config.js')

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    port: 8080,
    host: '0.0.0.0',
    overlay: {
      errors: true
    },
    historyApiFallback: {
      index: '/index.html'
    }
  }
})

webpack.build.js

const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const merge = require('webpack-merge')
const common = require('./webpack.config.js')

module.exports = merge(common, {
  mode: 'production',
  optimization: {
    splitChunks: {
      chunks: 'initial',
      automaticNameDelimiter: '.',
      cacheGroups: {
        commons: {
          name: 'commons',
          chunks: 'initial',
          minChunks: 2,
          priority: 3
        },
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: 1
        }
      }
    },
    runtimeChunk: {
      name: entrypoint => `manifest.${entrypoint.name}`
    }
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css'
    }),
    new CleanWebpackPlugin(
      ['dist'],
      {
        root: path.join(__dirname, '../')
      }
    )
  ]
})

修改package.json的命令:

"dev": "cross-env NODE_ENV=development webpack-dev-server --config config/webpack.dev.js",
"build": "cross-env NODE_ENV=production webpack --config config/webpack.build.js --progress --inline --colors"

现在分别执行 npm run dev 和 npm run build 就会得到你想要的了。

传送门:

webpack4系列教程

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

推荐阅读更多精彩内容