При горячей перезагрузке модуля первоначальный запрос страницы занимает 10-20 секунд с помощью Webpack, Koa, Vue.js

#node.js #webpack #localhost #koa #webpack-hmr

#node.js #webpack #localhost #koa #webpack-hmr

Вопрос:

По какой-то причине большинство обновлений страницы повторно запрашивают bundle.js файл, и загрузка с локального хостинга занимает около 10-15-20 секунд. Все это с локального хоста, и bundle.js размер файла составляет около 1 МБ. Запрос на этот файл, похоже, только сканируется, загружая несколько килобайт за раз.

Некоторые наблюдения:

  • После некоторого копания кажется, что он останавливается при первоначальном вызове сервера из __webpack_hmr, но я не уверен, поскольку этот вызов происходит после вызова bundle.js . Ниже приведен журнал потока запросов сервера.

  • Это происходит медленно только на страницах, содержащих более одного или двух компонентов, т.Е.. что угодно, кроме домашней страницы. Это намекает на идею, что это может быть связано с перезагрузкой горячего модуля.

  • Домашняя страница по-прежнему будет занимать> 5 секунд (иногда 10-20), как и другие страницы, но если я обновлю страницу с помощью Ctrl R, она вернется почти мгновенно. Если я выполняю обновление адресной строки, это занимает больше времени. Другие страницы по-прежнему занимают столько же времени, независимо от того, нажимаю ли я Ctrl R или перезагружаю адресную строку…
  • Обновление: я удалил замену горячего модуля, и это определенно кажется источником проблемы, так как страницы загружаются мгновенно без него.

Журнал запросов:

— Время отклика GET / = 609
мс —> GET / 200 647ms 2,55кб
<— GET /main.aafc9fb7f6a0c7f127edb04734d29547.css
—> GET /main.aafc9fb7f6a0c7f127edb04734d29547.css 200 17 мс 3,43 кб
<— /bundle.js
-> ПОЛУЧИТЬ /bundle.js 200 18 мс 1.29мб
<— GET /__webpack_hmr

А затем в консоли Chrome для этого запроса отображается: введите описание изображения здесь

Вот моя настройка:

  • Использование Koa в качестве серверной среды (с использованием потоковой передачи / фрагментации в начальном ответе)
  • Использование webpack с перезагрузкой горячего модуля
  • Использование Vue.js как фреймворк внешнего интерфейса, с рендерингом на стороне сервера
  • bundle.js подается в обычной сервировочно-статической упаковке.
  • bundle.js похоже, что он вообще не кэшируется. Почему это так?

Что касается Koa, я начал с какого-то стандартного пакета, чтобы выполнить весь этот рендеринг на стороне сервера и тому подобное. Это происходит с тех пор, как я начал возиться с этой настройкой и webpack в целом, поэтому я пытаюсь разобраться в этом. Это кажется немного случайным, иногда оно возвращается через <1 секунды, но в большинстве случаев это занимает более 10 секунд. Иногда более 30 секунд ?!

Я также пытался использовать разные библиотеки для обслуживания статических файлов, но все они, похоже, делают это.

Вот моя основная конфигурация webpack (‘webpack.client’, расширенная ниже):

 'use strict'
const path = require('path')
const webpack = require('webpack')
const AssetsPlugin = require('assets-webpack-plugin')
const assetsPluginInstance = new AssetsPlugin({path: path.join(process.cwd(), 'build')})
const postcss = [
  require('precss')()
  //require('autoprefixer')({browsers: ['last 2 versions']}),
]

module.exports = {
  entry: [
    './src/client-entry.js'
  ],
  output: {
    path: path.join(process.cwd(), 'build'),
    filename: 'bundle.js',
    publicPath: '/'
  },
  resolve: {
    extensions: ['', '.vue', '.js', '.json']
  },
  module: {
    loaders: [
      {
        test: /.vue$/,
        loaders: ['vue']
      },
      {
        test: /.js$/,
        loaders: ['babel'],
        exclude: [/node_modules/]
      },
      {
        test: /.json$/,
        loaders: ['json'],
        exclude: [/node_modules/]
      },
      {
        test: /.(png|jpg|gif|svg)$/,
        loader: 'url?limit=10000amp;name=images/[hash].[ext]',
        include: path.src,
      },
      {
        test: /.woff($|?)|.woff2($|?)|.ttf($|?)|.eot($|?)|.svg($|?)/,
        loader: 'url-loader',
        include: path.src,
      }
    ]
  },
  node: { net: 'empty', dns: 'empty' },
  postcss,
  vue: {
    postcss,
    loaders: {}
  },
  plugins: [
    assetsPluginInstance
  ]
}
  

А также это (расширяет предыдущее):

 'use strict'
const webpack = require('webpack')
const config = require('./webpack.client')
const ExtractTextPlugin = require('extract-text-webpack-plugin')

config.entry.push('webpack-hot-middleware/client')
//config.devtool = 'inline-eval-cheap-source-map'
config.plugins = config.plugins.concat([
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NoErrorsPlugin(),
  new webpack.DefinePlugin({
    '__DEV__': true,
    'process.env.NODE_ENV': JSON.stringify('development')
  }),
  new ExtractTextPlugin('[name].[contenthash].css')
])
config.vue.loaders = {
  postcss: ExtractTextPlugin.extract(
    'vue-style-loader',
    'css-loader?sourceMap'
  ),
  css: ExtractTextPlugin.extract(
    'vue-style-loader',
    'css-loader?sourceMap'
  )
}

module.exports = config
  

Вот мой сервер index.js файл для Koa:

 import path from 'path'
import fs from 'fs'
import Koa from 'koa'
import convert from 'koa-convert'
//import serve from 'koa-static-server'
import serveStatic from 'koa-static'
import {PassThrough} from 'stream'
import {createBundleRenderer} from 'vue-server-renderer'
import serialize from 'serialize-javascript'
import MFS from 'memory-fs'
import assets from '../build/webpack-assets'
import cookie from 'koa-cookie'

let renderer
const createRenderer = fs => {
  const bundlePath = path.resolve(process.cwd(), 'build/server-bundle.js')
  return createBundleRenderer(fs.readFileSync(bundlePath, 'utf-8'))
}

const app = new Koa();

app.use(cookie());

if (process.env.NODE_ENV === 'development') {
  // DEVELOPMENT, with hot reload
  const webpack = require('webpack')
  const webpackConfig = require('../config/webpack.client.dev')
  const compiler = webpack(webpackConfig)
  const devMiddleware = require('koa-webpack-dev-middleware')
  const hotMiddleware = require('koa-webpack-hot-middleware')

  app.use(convert(devMiddleware(compiler, {
    publicPath: webpackConfig.output.publicPath,
    stats: {
      colors: true,
      modules: false,
      children: false,
      chunks: false,
      chunkModules: false
    }
  })))

  app.use(convert(hotMiddleware(compiler)))

  // server renderer
  const serverBundleConfig = require('../config/webpack.bundle')
  const serverBundleCompiler = webpack(serverBundleConfig)
  const mfs = new MFS()

  serverBundleCompiler.outputFileSystem = mfs
  serverBundleCompiler.watch({}, (err, stats) => {
    if (err) throw err
    stats = stats.toJson()
    stats.errors.forEach(err => console.error(err))
    stats.warnings.forEach(err => console.warn(err))
    renderer = createRenderer(mfs)
  })
} 
else {
  // PRODUCTION
  // use nginx to serve static files in real
  //app.use(convert(serve({rootDir: path.join(process.cwd(), 'build'), rootPath: '/static'})))
  app.use(serveStatic(path.join(process.cwd(), 'build')));
  renderer = createRenderer(fs)
}

app.use(ctx => {
  var start = new Date;
  ctx.type = 'text/html; charset=utf-8'
  const context = {url: ctx.url}
  const title = 'Tripora';
  const stream = new PassThrough()

  console.log("Checking if server-side cookie exists...");
  // See if request sent over an authentication token in their cookies
  if(ctx.cookie amp;amp; ctx.cookie.token) {
    console.log("Found cookie token.");
    context.token = ctx.cookie.token;
  }

  stream.write(`<!DOCTYPE html><html style="min-height: 100%;"><head><meta charset="utf-8"/><title>${title}</title>${assets.main.css ? `<link rel="stylesheet" href="${assets.main.css}"/>` : ''}</head><body style="min-height: 100%;">`)

  const renderStream = renderer.renderToStream(context)
  let firstChunk = true

  renderStream.on('data', chunk => {
    // we tell the request to ignore files as an initial reuqest
    var isPage = ctx.url.split(".").length == 1;

    if (firstChunk amp;amp; context.initialState amp;amp; isPage) { 
      stream.write(`<script>window.__INITIAL_STATE__=${serialize(context.initialState, {isJSON: true})}</script>${chunk}`)
      firstChunk = false
    } else {
      stream.write(chunk)
    }
  })

  renderStream.on('end', () => {
    stream.write(`<script src="${assets.main.js}"></script></body></html>`)

    var ms = new Date - start;
    //ctx.set('X-Response-Time', ms   'ms');
    console.log("-- Response time %s %s = %sms", ctx.method, ctx.originalUrl, ms);

    ctx.res.end()
  })

  renderStream.on('error', err => {
    console.log("ERROR", err.stack);
    throw new Error(`something bad happened when renderToStream: ${err}`)
  })

  ctx.status = 200
  ctx.body = stream
})

const port = process.env.NODE_PORT || 80
app.listen(port, () => {
  console.log(`==> Listening at http://localhost:${port}`)
})
  

Кто-нибудь знает, почему первоначальный запрос HMR занимает так много времени и кажется таким случайным (иногда 5 секунд, иногда 30 секунд)? Технология.

Комментарии:

1. Вы когда-нибудь это понимали?