我是webpack的新手,所以这对我来说可能是一个愚蠢的错误。
这是我的项目设置(root,至少是相关部分):
+-- public
| |
| +-- index.html
|
+-- src
| |
| +-- App.vue
| +-- main.js
| +-- assets
|
+-- package.json
|
+-- webpack.config.js
现在我想使用webpack-dev(和hot)-middleware来为我的index.html提供服务,并在我的src文件夹中创建一个内存包。现在我可以设置中间件(通过npm页面),我看到捆绑包被创建(通过登录控制台),但有两件事我不清楚:
有人可以解释一下这个中间件是如何工作的吗?这是我的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
})
])
}
答案 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并将你的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