使用vuejs项目

时间:2016-11-28 07:49:37

标签: express webpack vue.js

我是webpack的新手,所以这对我来说可能是一个愚蠢的错误。

这是我的项目设置(root,至少是相关部分):

 +-- public
 |  |  
 |  +-- index.html
 |    
 +-- src
 |  |  
 |  +-- App.vue
 |  +-- main.js
 |  +-- assets
 |    
 +-- package.json
 |    
 +-- webpack.config.js

现在我想使用webpack-dev(和hot)-middleware来为我的index.html提供服务,并在我的src文件夹中创建一个内存包。现在我可以设置中间件(通过npm页面),我看到捆绑包被创建(通过登录控制台),但有两件事我不清楚:

  • 如何投放index.html
  • 如何使用在内存中创建的捆绑包?

有人可以解释一下这个中间件是如何工作的吗?这是我的webpack配置文件(需要插入中间件,它只是通过vue-cli创建的webpack配置文件的副本):

var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js'
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          // vue-loader options go here
        }
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.common.js'
    }
  },
  devServer: {
    historyApiFallback: true,
    noInfo: true
  },
  devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  // http://vue-loader.vuejs.org/en/workflow/production.html
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true
    })
  ])
}

我知道这可能不是正确的配置,有人可能会指出一些事情吗?

提前感谢您的帮助!

修改(此设置有效)

我的server.js现在:

var express = require('express');
var logger = require('morgan');
var bodyParser = require('body-parser');
var exphbs  = require('express-handlebars');
var helmet = require('helmet');
var redis = require('redis');
var redisAdapter = require('socket.io-redis');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
// use the redis adapter to create sticky sessions, this is needed because of the different clusters
io.adapter(redisAdapter( require('./app/lib/config').credentials.redis.url ));

//setup security ===============================================================
require('./app/lib/security-setup')(app, helmet);

// configuration ===============================================================
app.use(logger('dev')); // log every request to the console

// set up our express application ==============================================

// Make the body object available on the request
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

//set handlebars as default templating engine
app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');

// serve the static content ====================================================
if (app.settings.env === 'development') {
  var webpackConfig = require('./webpack.config.js')
  var compiler = require('webpack')(webpackConfig)
  var devMiddleware = require('webpack-dev-middleware')(compiler, {
    publicPath: webpackConfig.output.publicPath,
  })
  var hotMiddleware = require('webpack-hot-middleware')(compiler)

  app.use(devMiddleware)
  app.use(hotMiddleware)
} else {
    app.use(express.static(__dirname + '/public'));
}

// set up global variables =====================================================
app.use(function(req, res, next) {
  //set the io object on the response, so we can access it in our routes
  res.io = io;
  next();
});

// routes ======================================================================
require('./app/routes.js')(app); // load our routes and pass in our app

// export so bin/www can launch ================================================
module.exports = {app: app, server: server};

我的./bin/www:

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../server').app;
var cluster = require('cluster');
var debug = require('debug')('temp:server');
var http = require('http');
var numCPUs = process.env.WORKERS || require('os').cpus().length;

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  // If a worker dies, log it to the console and start another worker.
  cluster.on('exit', function(worker, code, signal) {
    console.log('Worker ' + worker.process.pid + ' died.');
    cluster.fork();
  });

  // Log when a worker starts listening
  cluster.on('listening', function(worker, address) {
    console.log('Worker started with PID ' + worker.process.pid + '.');
  });

} else {
  /**
   * Create HTTP server.
   */

  var server = require('../server').server;

  /**
   * Listen on provided port, on all network interfaces.
   */
  server.listen(port);

  server.on('error', onError);
  server.on('listening', onListening);
}

// The rest of the bin/www file.....

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

我的工作webpack.config.js:

var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: [
    'webpack/hot/dev-server',
    'webpack-hot-middleware/client',
    './src/main.js'
  ],
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js'
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          // vue-loader options go here
        }
      },
      {
        test: /\.less$/,
        loader: "style!css!less"
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.common.js'
    }
  },
  devServer: {
    historyApiFallback: true,
    noInfo: true
  },
  devtool: '#eval-source-map',
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: path.resolve(__dirname, 'public/index.html'),
      inject: true
    }),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ]
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  // http://vue-loader.vuejs.org/en/workflow/production.html
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true
    })
  ])
}

1 个答案:

答案 0 :(得分:7)

如何投放index.html

要提供index.html文件,您需要运行dev服务器。听起来您已成功执行此操作,具体取决于您在内存中创建捆绑包的日志记录。但是我在你的设置中看不到它的文件?我假设下面的另一个文件名为dev-server.js,它将是您提供应用的入口点,即npm run dev

<强>的package.json

"scripts": {
  "dev": "node dev-server.js",
  ...

在webpack中,这个开发服务器通常是快速的,它是你传递给你的index.html的快速服务器的配置。由于您需要热重新加载,您将通过中间件层传递您的webpack配置。

对于热重新加载,您需要两个主要的中间件:

  • 的WebPack-DEV-中间件
  • 的WebPack-热中间件

然后你需要将你的配置传递给webpack并将你的webpack编译器传递给中间件,即

<强> DEV-server.js

var app = require('express')()

var webpackConfig = require('./webpack.config.js')

var compiler = require('webpack')(webpackConfig)

var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: webpackConfig.output.publicPath,
})

var hotMiddleware = require('webpack-hot-middleware')(compiler)

app.use(devMiddleware)

app.use(hotMiddleware)

现在密钥文件成为您的webpack配置,上面引用为:./webpack.config.js

这会引出您的下一个问题:如何使用在内存中创建的捆绑包?

您在上面发布的文件看起来是正确的,关于使用捆绑包的关键部分保存在输出中,您有:

<强> webpack.config.js

output: {
  path: path.resolve(__dirname, './dist'),
  publicPath: '/dist/',
  filename: 'build.js'
},

您正在dist/build.js创建相对于当前工作目录的捆绑包。这基本上是您需要在index.html中指向该文件的任何引用,即<script src="/dist/build.js"></script>

你如何做到这一点可以手动但是我们经常添加一个webpack插件来自动在你的输出html中构建这个脚本标签(在这种情况下再次在内存中):

<强> webpack.config.js

plugins: [
  // https://github.com/ampedandwired/html-webpack-plugin
  new HtmlWebpackPlugin({
    filename: 'index.html',
    template: path.resolve(__dirname, 'public/index.html'),
    inject: true
  }),
  ...

HtmlWebpackPlugin现在基本上是你如何引用输出文件的引用:filename以及它存储的关键位置:template所以如果你想移动你的index.html文件,这就是你的位置告诉webpack在哪里找到它。 HtmlWebpackPlugin现在将输出'index.html'放在前面引用的publicPath处,因此要访问此文件,您可以调用/dist/index.html

最后你需要一些热插拔的插件,所以你的整个webpack插件数组看起来像:

<强> webpack.config.js

plugins: [
  new webpack.optimize.OccurenceOrderPlugin(),
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NoErrorsPlugin(),
  // https://github.com/ampedandwired/html-webpack-plugin
  new HtmlWebpackPlugin({
    filename: 'index.html',
    template: 'bar/index.html',
    inject: true
  })
]

现在我们返回dev-server.js文件 - 或者你正在配置的所有调用文件 - 并启动配置的快速服务器:

<强> DEV-server.js

module.exports = app.listen(8080, function (err) {
  if (err) {
    console.log(err)
    return
  }
})

因此,使用上面的配置,您将打开以下uri:localhost:8080/dist/index.html