从vue-10betcli学webpack配置2--针对webpack3

来源:http://www.chinese-glasses.com 作者:Web前端 人气:152 发布时间:2020-04-07
摘要:时间: 2019-10-12阅读: 91标签: 环境前言 上一篇: 从vue-cli学webpack配置--针对webpack2 现在大家用vue-cli工具新建的webpack工程应该是基于webpack3,与上一篇的不同之处在于它不在是用webpack-dev

时间: 2019-10-12阅读: 91标签: 环境前言

上一篇:从vue-cli学webpack配置--针对webpack2
  现在大家用vue-cli工具新建的webpack工程应该是基于webpack3,与上一篇的不同之处在于它不在是用webpack-dev-middleware、webpack-hot-middleware来做热更新的,而是直接用webpack-dev-server,当然整个配置更加的简洁了。生产环境构建的配置与上一篇的区别是一致,我们直接看开发环境。
第一部分  webpack-dev-server基础使用
webpack-dev-server是一个小型node express 服务,它是一个独立的npm包,npm install webpack-dev-server 后,你就可以通过命令启动它。
基础命令:

网上有关ssr开发环境搭建的文章不算多,就算找到也是比较高级的,不太适合新手入坑;这篇内容只抽取了其中最重要的部分,实现最基础的开发环境搭建;所谓开发环境无非两件事:自动打包·自动刷新页面,叫法比较土,也可以叫热更新,热加载。

webpack-dev-server --inline --process --config  build/webpack.dev.conf.js
/* inline 
dev-server有两种模式,一种是iframe模式,一种是inline模式。
iframe模式,访问时需要 http://host:port/webpack-dev-server/path,加多一个webpack-dev-server,而inline则不用,推荐用inline

progress :将运行进度输出到控制台
config:  指定配置文件
*/

自动更新renderer

然后我们看到package.json 也是这样启动服务的:

先看目录结构没啥东西,新增了一个hot.config.js文件,用来放置热加载的配置;先看下server.js

10bet 1

//server.jsconst express = require('express');const chalk = require('chalk');const server = express();let renderer;const hotServer = require('./webpack.hot.config.js')//我们希望通过不停的执行下面这样一个函数的回调,从新实例化renderer,已达到自动更新的目的;hotServer(server,({serverBundle,clientManifest})={ console.log('hot***************************************************') renderer = require('vue-server-renderer').createBundleRenderer(serverBundle,{ runInNewContext: false, // 推荐 template: require('fs').readFileSync('./index.html', 'utf-8'), clientManifest // (可选)客户端构建 manifest })})server.use('/',express.static('./dist')) // 设置访问静态文件路径server.get('*', (req, res) = { res.set('content-type', "text/html"); const context = { url:req.url } renderer.renderToString(context, (err, html) = { if (err) { res.status(500).end('Internal Server Error') return } else { res.end(html) } }) })server.listen(8080,function(){ let ip = getIPAdress(); console.log(`服务器开在:${chalk.green(ip)}:${chalk.yellow(8080)}`)})function getIPAdress(){//node下的os模块可以拿到启动该文件的服务端的部分信息,细节自己去node上面查 var interfaces = require('os').networkInterfaces(); for (var devName in interfaces) { var iface = interfaces[devName]; for (var i = 0; i  iface.length; i++) { var alias = iface[i]; if (alias.family === 'IPv4'  alias.address !== '127.0.0.1'  !alias.internal) { return alias.address; } } }}

packge.json

跟自动化有关的代码只有和hotServer有关的几行代码,其实也是经过分析,对于这个server服务,有用的文件只有服务端配置vue-ssr-server-bundle.json和客户端配置vue-ssr-client-manifest.json,我们只要在这两个文件打包之后从新实例化renderer就可以了,应为renderer实例化是通过加载静态文件而生产的一个不再变化的实例;

那我们就看build/webpack.dev.conf.js:

webpack.hot.config.js也可以写在server.js里面,不过看上去就不太好看,也不符合模块开发的原则;

'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')

const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)

// 这里同样也是合并基本的配置,加入开发环境的配置
// 指定devServer
const devWebpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
  },
  // cheap-module-eval-source-map is faster for development
  devtool: config.dev.devtool,  //指定生成那种形式的souceMap,cheap-module-eval-source-map这个是适合开发环境

  // these devServer options should be customized in /config/index.js
  devServer: {
    clientLogLevel: 'warning', // 客户端报错等级
    historyApiFallback: {  // 当使用 HTML5 History API 时,下面匹配的路径,出现404 响应都可能需要被替代为 index.html
      rewrites: [
        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
      ],
    },
    hot: true, //启用热部署
    contentBase: false, //告诉服务观察对应目录文件更改情况,文件更改后,会触发重新加载;这里为false // since we use CopyWebpackPlugin.
    compress: true,
    host: HOST || config.dev.host,  // 指定可以访问的主机地址,默认是localhost,允许外网范围则是0.0.0.0
    port: PORT || config.dev.port, // 端口
    open: config.dev.autoOpenBrowser, // 是否自动打开浏览器
    overlay: config.dev.errorOverlay  
      ? { warnings: false, errors: true }
      : false,  // 当出现编译器错误或警告时,在浏览器中显示全屏叠加,其实就是我们经常看到的那个报错页面
    publicPath: config.dev.assetsPublicPath,
    proxy: config.dev.proxyTable,  
    quiet: true, // necessary for FriendlyErrorsPlugin   //启用 quiet 后,除了初始启动信息之外的任何内容都不会被打印到控制台
    watchOptions: { // webpack 使用文件系统(file system)获取文件改动的通知,一些情况下不生效,所有采用轮询
      poll: config.dev.poll,
    }
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': require('../config/dev.env')
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
    new webpack.NoEmitOnErrorsPlugin(),
    // https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    }),
    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.dev.assetsSubDirectory,
        ignore: ['.*']
      }
    ])
  ]
})

module.exports = new Promise((resolve, reject) => {
  portfinder.basePort = process.env.PORT || config.dev.port
  portfinder.getPort((err, port) => {
    if (err) {
      reject(err)
    } else {
      // publish the new Port, necessary for e2e tests
      process.env.PORT = port
      // add port to devServer config
      devWebpackConfig.devServer.port = port

      // Add FriendlyErrorsPlugin
      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
        compilationSuccessInfo: {
          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
        },
        onErrors: config.dev.notifyOnErrors
        ? utils.createNotifierCallback()
        : undefined
      }))

      resolve(devWebpackConfig)
    }
  })
})

自动打包

这里实际上也是合并基础webpack配置,最后resolve出去。当我们通过命令行调动的webpack-dev-server,指定它的config的时候,程序为我们加载这个配置,提供给webpack-dev-server使用,这个dev-server是使用webpack帮我们打包,打包的东西不是输出到dist而是存在内存中。这个有两个注意点:
1、静态资源更新怎么检测到:
A 是 contentbase指定目录,进行检测,然后我们去手动更新目录的下的静态资源
B vue-cli工程使用CopyWebpackPlugin,同时启动hot热部署,当我们更改静态资源,CopyWebpackPlugin会帮我们复制过去,所以我们不需要手动去更改发布目录的下的静态资源,而且也不需要dev-server去帮我们检测发布目录的静态资源
2、webpack-dev-server是如何实现热替换
这点我在官网上找到答案:

webpack自动打包有watch,或者使用webpack-dev-serve,dev-server会自己启一个服务,然而我们有自己的server,他们之间通信不是不可以,只是比较困难,不适用;watch也是一样,比较独立;webpack可以独立使用,然而它也只是node中的一个模块,可以作为插件使用,而且可以通过其他插件和express结合使用;

10bet 2

webpack-dev-middleware

官网的意思就是说,如果你启动了dev-server配置中的hot,那你需要搭配webpack.HotModuleReplacementPlugin, 这个插件是用来实现HRM,而且这个插件会有dev-server或者webpack自动调用,以实现热更新。

webpack-dev-middleware是实现热加载的核心组件,看一下webpack.hot.config.js的内容

最后啰嗦几句,为啥是用portfinder? 这个是一个检查当前机器开放端口的工具,因为我们启动的时候会帮我们看是否端口冲突,冲突则报错,不冲突这程序继续,暴露我们配置给调用我们的命令行进程。

//webpack.hot.config.jsconst webpack = require('webpack');//新增webpack-dev-middleware插件const webpackDevMiddleware = require('webpack-dev-middleware');const path=require('path')const clientConfig=require('./webpack.client.config.js')const serverConfig=require('./webpack.server.config.js')//输出一个函数给server使用module.exports = function(server,callBack){ let b,c; //这里先定义一个run方法,保证vue-ssr-server-bundle.json和vue-ssr-client-manifest.json都有的情况才去执行回调; function run(){ console.log('run'); if(b  c){ console.log('runend ') callBack({serverBundle:JSON.parse(b),clientManifest:JSON.parse(c)}) } } //生成vue-ssr-server-bundle.json //实例化webpack const serverComplier = webpack(serverConfig); middleware = webpackDevMiddleware(serverComplier) server.use(middleware); //serverComplier是webpack返回的实例,plugin方法可以捕获事件,done表示打包完成 serverComplier.plugin('done',complation = { console.log('serverdown') //核心内容,middleware.fileSystem.readFileSync是webpack-dev-middleware提供的读取内存中文件的方法; //不过拿到的是二进制,可以用JSON.parse格式化; let serverBundle=middleware.fileSystem.readFileSync(path.join(serverConfig.output.path, 'vue-ssr-server-bundle.json')) //把拿到的文件复制给b b=serverBundle; run(); }) //生成vue-ssr-client-manifest.json,方法和上面一模一样 const clientComplier = webpack(clientConfig) clientMiddleware = webpackDevMiddleware(clientComplier),{ noInfo: true, stats: { colors: true } } server.use(clientMiddleware) clientComplier.plugin('done',complation={ console.log('clientdown') let clientBundle=clientMiddleware.fileSystem.readFileSync(path.join(clientConfig.output.path, 'vue-ssr-client-manifest.json')) c=clientBundle; run() })}

整体webpack-dev-server的配置比上一篇使用node express服务,搭配webpck-dev-middleware和webpack-hot-middleware来实现热更新要来得简洁多。不过实际中,dev-server也是一样的,只不过人家帮你弄好罢了。但是配置更清晰易懂。

本文由10bet发布于Web前端,转载请注明出处:从vue-10betcli学webpack配置2--针对webpack3

关键词:

上一篇:理解二进制操作

下一篇:随机数10bet

频道精选

最火资讯