vue 多项目 依赖webpack开发共用 配置

原创 2016年06月08日 19:01:57

由于项目历史遗留问题,项目目录不尽合理。如下
root //其它文件
|–vue_dev // 基于vue开发的
……..|—package.json // 不解释
……..|—node_modules // 不演示
……..|—build // 打包运行代码
……..|—views // 下面会有很多项目
……..|—utils // 放一些公共的有用的东西
|–web //输出文件

根据项目目录,在view 下新建shaoxia_demo文件夹。其中包含 index.html ,index.js 分别如下。
index.html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>首页</title>
</head>
<body>
<!-- vue的组件以自定义标签的形式使用 -->
<favlist></favlist>
</body>
</html>

index.js

/**
 * Created by keli on 2016/6/8.
 */
import Vue from 'Vue'
import Favlist from './components/Favlist'

new Vue({
  el: 'body',
  components: { Favlist }
})

在components目录下新建一个 Favlist.vue 文件,作为我们的第一个组件:

<template>
    <div v-for="n in 4">{{msg}}</div>
</template>

<script>
    export default {
        data () {
            return {
                msg: 'Hello World!'
            }
        }
    }
</script>

<style>
    html{
        background: #def;
    }
</style>

我希望打包相关的代码跟实用代码分开。所以在 vue_dev下新建了一个build文件夹(先不要着急目录结构是否合理,后续步骤会说服你这是合理的)。build文件夹下新建webpack.config.js。如下:

/**
 * Created by keli on 2016/6/8.
 */
// nodejs 中的path模块
var path = require('path');

module.exports = {
  // 入口文件,path.resolve()方法,可以结合我们给定的两个参数最后生成绝对路径,最终指向的就是我们的index.js文件
  entry: path.resolve(__dirname, '../views/shaoxia_demo/index.js'),
  // 输出配置
  output: {
    // 输出路径是 myProject/output/static
    path: path.resolve(__dirname, '../../web/shaoxia_demo'),
    publicPath: 'static/',
    filename: '[name].[hash].js',
    chunkFilename: '[id].[chunkhash].js'
  },
  module: {

    loaders: [
      // 使用vue-loader 加载 .vue 结尾的文件
      {
        test: /\.vue$/,
        loader: 'vue'
      }
    ]
  }
}

在build目录下。执行:

webpack --display-modules --display-chunks

sorry,不出意外的话,会报错,它说没有发现 ‘./components/Favlist’ 模块,而我们明明有 ./components/Favlist.vue 文件,为什么它没发现呢?其实是这样的,当webpack试图去加载模块的时候,它默认是查找以 .js 结尾的文件的,它并不知道 .vue 结尾的文件是什么鬼玩意儿,所以我们要在配置文件中告诉webpack,遇到 .vue 结尾的也要去加载(就算不报错,最好也加上),添加 resolve 配置项,如下:

/**
 * Created by keli on 2016/6/8.
 */
// nodejs 中的path模块
var path = require('path');

module.exports = {
  // 入口文件,path.resolve()方法,可以结合我们给定的两个参数最后生成绝对路径,最终指向的就是我们的index.js文件
  entry: path.resolve(__dirname, '../views/shaoxia_demo/index.js'),
  // 输出配置
  output: {
    // 输出路径是 myProject/output/static
    path: path.resolve(__dirname, '../../web/shaoxia_demo'),
    publicPath: 'static/',
    filename: '[name].[hash].js',
    chunkFilename: '[id].[chunkhash].js'
  },
  resolve: {
    extensions: ['', '.js', '.vue']
  },
  module: {

    loaders: [
      // 使用vue-loader 加载 .vue 结尾的文件
      {
        test: /\.vue$/,
        loader: 'vue'
      }
    ]
  }
}

这样,当我们去加载 ‘./components/Favlist’ 这样的模块时,webpack首先会查找 ./components/Favlist.js 如果没有发现Favlist.js文件就会继续查找 Favlist.vue 文件,现在再次运行构建命令,我们成功了,这时我们会在我们的输出目录中看到一个js文件:
之所以会这样输出,是因为我们的 webpack.config.js 文件中的输出配置中指定了相应的输出信息,这个时候,我们修改 index.html ,将输出的js文件引入:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>首页</title>
</head>
<body>
<!-- vue的组件以自定义标签的形式使用 -->
<favlist></favlist>
<script src="../../../web/shaoxia_demo/main.900ea8a3f270c8f19b6c.js"></script>
</body>
</html>

不出意外的话,页面空白,控制台会报错Uncaught SyntaxError: Unexpected token import。是因为我们用了es6语法,但没有把它转成浏览器认识的。所以,继续在webpack.config.js中加loader。这次添加的是babel-loader。

/**
 * Created by keli on 2016/6/8.
 */
// nodejs 中的path模块
var path = require('path');

module.exports = {
  // 入口文件,path.resolve()方法,可以结合我们给定的两个参数最后生成绝对路径,最终指向的就是我们的index.js文件
  entry: path.resolve(__dirname, '../views/shaoxia_demo/index.js'),
  // 输出配置
  output: {
    // 输出路径是 myProject/output/static
    path: path.resolve(__dirname, '../../web/shaoxia_demo'),
    publicPath: 'static/',
    filename: '[name].[hash].js',
    chunkFilename: '[id].[chunkhash].js'
  },
  resolve: {
    extensions: ['', '.js', '.vue']
  },
  module: {

    loaders: [
      // 使用vue-loader 加载 .vue 结尾的文件
      {
        test: /\.vue$/,
        loader: 'vue'
      },
      {
        test:/\.js$/,
        loader: 'babel?presets=es2015',
        exclude: /node_modules/
      }
    ]
  }
}

再次编译,打开这个html文件,可以正确看到页面了。

那么问题来了,难道我们每次都要手动的引入输出的js文件吗?因为每次构建输出的js文件都带有 hash 值,如 main.900ea8a3f270c8f19b6c.js,就不能更智能一点吗?每次都自动写入?怎么会不可能,否则这东西还能火吗,要实现这个功能,我们就要使用webpack的插件了,html-webpack-plugin插件,这个插件可以创建html文件,并自动将依赖写入html文件中。
首先在vue_dev中安装 html-webpack-plugin 插件:

npm install html-webpack-plugin --save-dev

然后再修改配置项,添加这个插件,让它发挥作用:

/**
 * Created by keli on 2016/6/8.
 */
// nodejs 中的path模块
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // 入口文件,path.resolve()方法,可以结合我们给定的两个参数最后生成绝对路径,最终指向的就是我们的index.js文件
  entry: path.resolve(__dirname, '../views/shaoxia_demo/index.js'),
  // 输出配置
  output: {
    // 输出路径是 myProject/output/static
    path: path.resolve(__dirname, '../../web/shaoxia_demo'),
    publicPath: 'static/',
    filename: '[name].[hash].js',
    chunkFilename: '[id].[chunkhash].js'
  },
  resolve: {
    extensions: ['', '.js', '.vue']
  },
  module: {
    loaders: [
      // 使用vue-loader 加载 .vue 结尾的文件
      {
        test: /\.vue$/,
        loader: 'vue'
      },
      {
        test:/\.js$/,
        loader: 'babel?presets=es2015',
        exclude: /node_modules/
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', //相对于output.path,产出路径。
      template: path.resolve(__dirname, '../views/shaoxia_demo/index.html'), //html模板,绝对路径。
      inject: true
    })
  ]
}

然后再次执行构建命令,成功之后,看你的输出目录,多出来一个index.html文件,双击它,代码正确执行,你可以打开这个文件查看一下,webpack自动帮我们引入了相应的文件。

问题继续来了,难道每次我们都要构建之后才能查看运行的代码吗?那岂不是很没有效率,别担心,webpack提供了几种方式,进行热加载,在开发模式中,我们使用这种方式来提高效率,这里要介绍的,是使用 webpack-dev-middleware中间件和webpack-hot-middleware中间件,首先在vue_dev中安装两个中间件:

npm install webpack-dev-middleware webpack-hot-middleware --save-dev

另外,还要安装express,这是一个nodejs框架

npm install express --save-dev

在开始之前,我先简单介绍一下这两个中间件,之所以叫做中间件,是因为nodejs的一个叫做express的框架中有中间件的概念,而这两个包要作为express中间件使用,所以称它们为中间件,那么他们能干什么呢?
1.webpack-dev-middleware
我们之前所面临的问题是,如果我们的代码改动了,我们要想看到浏览器的变化,需要先对项目进行构建,然后才能查看效果,这样对于开发效率来讲,简直就是不可忍受的一件事,试想我仅仅修改一个背景颜色就要构建一下项目,这尼玛坑爹啊,好在有webpack-dev-middleware中间件,它是对webpack一个简单的包装,它可以通过连接服务器服务那些从webpack发射出来的文件,它有一下几点好处:
1、不会向硬盘写文件,而是在内存中,注意我们构建项目实际就是向硬盘写文件。
2、当文件改变的时候,这个中间件不会再服务旧的包,你可以直接帅新浏览器就能看到最新的效果,这样你就不必等待构建的时间,所见即所得。
下面我们在build目录中创建一个 dev-server.js 的文件,并写入一下内容:

/**
 * Created by keli on 2016/6/8.
 */
// 引入必要的模块
var express = require('express')
var webpack = require('webpack')
var config = require('./webpack.config')

// 创建一个express实例
var app = express()

// 调用webpack并把配置传递过去
var compiler = webpack(config)

// 使用 webpack-dev-middleware 中间件
var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: config.output.publicPath,
  stats: {
    colors: true,
    chunks: false
  }
})

// 注册中间件
app.use(devMiddleware)

// 监听 8888端口,开启服务器
app.listen(8888, function (err) {
  if (err) {
    console.log(err)
    return
  }
  console.log('Listening at http://localhost:8888')
})

此时,我们在vue_dev运行下面的命令,开启服务:

node build/dev-server.js

如果控制台没有报错,那就说明服务启动成功。
接下来打开浏览器,输入:

http://localhost:8888/views/shaoxia_demo/index.html

如果不出意外的话,会报404。
我们要对我们的 webpack.config.js 配置文件做两处修改:
1 将publicPath改为’/’

output: {
    // 输出路径相对于vue_dev是 ../web/shaoxia_demo
    path: path.resolve(__dirname, '../../web/shaoxia_demo'),
    publicPath: '/',
    filename: '[name].[hash].js',
    chunkFilename: '[id].[chunkhash].js'
},

2.将 plugins 中 HtmlWebpackPlugin 中的 filename 修改为 ‘views/shaoxia_demo/index.html’

plugins: [
    new HtmlWebpackPlugin({
          filename: 'views/shaoxia_demo/index.html',
          template: path.resolve(__dirname, '../views/shaoxia_demo/index.html'), //html模板,绝对路径。
          inject: true
        })
]

重启服务,刷新页面,OK了。
是这样开发模式下的确是成功了,可是我们直接修改了 webpack.config.js 文件,这就意味着当我们执行 构建命令 的时候,配置变了,那么我们的构建也跟着变了,所以,一个好的方式是,不去修改webpack.config.js文件,我们在build目录下新建一个 webpack.dev.conf.js文件,意思是开发模式下要读取的配置文件,并写入一下内容:

var HtmlWebpackPlugin = require('html-webpack-plugin')
var path = require('path');
// 引入基本配置
var config = require('./webpack.config');

config.output.publicPath = '/';

config.plugins = [
  new HtmlWebpackPlugin({
    filename: 'views/shaoxia_demo/index.html',
    template: path.resolve(__dirname, '../views/shaoxia_demo/index.html'), //html模板,绝对路径。
    inject: true
  })
];

module.exports = config;

这样,我们在dev环境下的配置文件中覆盖了基本配置文件,我们只需要在dev-server.js中将

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

修改为:

var config = require('./webpack.dev.conf')

即可,然后,重启服务,刷新浏览器,你应该得到同样的成功结果,而这一次当我们执行构建命令:

webpack --display-modules --display-chunks --config build/webpack.config.js

并不会影响构建输出,因为我们没有直接修改webpack.config.js文件。

现在我们已经使用 webpack-dev-middleware 搭建基本的开发环境了,

但是

我们并不满足,因为我们每次都要手动去刷新浏览器,所谓的热加载,意思就是说能够追踪我们代码的变化,并自动更新界面,甚至还能保留程序状态。要完成热加载,我们就需要使用另外一个中间件 webpack-hot-middleware

2.webpack-hot-middleware

webpack-hot-middleware 只配合 webpack-dev-middleware 使用,它能给你提供热加载。
它的使用很简单,总共分4步:
第1步、安装,我们上面已经安装过了
第2步、在 webpack.dev.conf.js 配置文件中添加三个插件,如下:

var webpack = require('webpack');
// 添加三个插件
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),

第3步、在 webpack.config.js 文件中入口配置中添加 ‘webpack-hot-middleware/client’,如下:

 entry: ['webpack-hot-middleware/client',path.resolve(__dirname, '../views/shaoxia_demo/index.js')],

第4步、在 dev-server.js 文件中使用插件

/**
 * Created by keli on 2016/6/8.
 */
// 引入必要的模块
var express = require('express')
var webpack = require('webpack')
var config = require('./webpack.dev.conf')

// 创建一个express实例
var app = express()

// 调用webpack并把配置传递过去
var compiler = webpack(config)

// 使用 webpack-dev-middleware 中间件
var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: config.output.publicPath,
  stats: {
    colors: true,
    chunks: false
  }
})
// 使用 webpack-hot-middleware 中间件
var hotMiddleware = require('webpack-hot-middleware')(compiler)


// 注册中间件
app.use(devMiddleware)
// 注册中间件
app.use(hotMiddleware)

// 监听 8888端口,开启服务器
app.listen(8888, function (err) {
  if (err) {
    console.log(err)
    return
  }
  console.log('Listening at http://localhost:8888')
})

ok,现在重启的服务,然后修改 Favlist.vue 中的页面背景颜色为 ‘#000’.然后查看你的浏览器,是不是你还没有刷新就已经得带改变了?如果没有,重启几次或者去倒杯水喝就好了。

那么这样就完美了吗?还没有,如果你细心,你会注意到,我们上面在第2步中修改了 webpack.config.js 这个基本配置文件,修改了入口配置,如下:

 entry: ['webpack-hot-middleware/client',path.resolve(__dirname, '../views/shaoxia_demo/index.js')],

这也会导致我们之前讨论过的问题,就是会影响构建,所以我们不要直接修改 webpack.config.js 文件,我们还是在 webpack.dev.conf.js 文件中配置,如下:

// 动态向入口配置中注入 webpack-hot-middleware/client
var devClient = 'webpack-hot-middleware/client';
Object.keys(config.entry).forEach(function (name, i) {
    var extras = [devClient]
    config.entry[name] = extras.concat(config.entry[name])
})

但是我们还是要讲 webpack.config.js 文件中的入口配置修改为多入口配置的方式,这个修改不会影响构建,所以无所谓:

entry:{
    index:path.resolve(__dirname, '../views/shaoxia_demo/index.js')
  },

重启你的服务,刷新一下浏览器,然后修改 Favlist.vue 中的背景色.再次查看浏览器,发现可以热加载。但是这样就结束了吗?还没有,不信你修改 index.html 文件,看看会不会热加载,实际上不会,你还是需要手动刷新页面,为了能够当 index.html 文件的改动也能够触发自动刷新,我们还需要做一些工作。

第一步:在 dev-server.js 文件中监听html文件改变事件,修改后的 dev-server.js 文件如下:

/**
 * Created by keli on 2016/6/8.
 */
// 引入必要的模块
var express = require('express')
var webpack = require('webpack')
var config = require('./webpack.dev.conf')

// 创建一个express实例
var app = express()

// 调用webpack并把配置传递过去
var compiler = webpack(config)

// 使用 webpack-dev-middleware 中间件
var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: config.output.publicPath,
  stats: {
    colors: true,
    chunks: false
  }
})
// 使用 webpack-hot-middleware 中间件
var hotMiddleware = require('webpack-hot-middleware')(compiler)

// webpack插件,监听html文件改变事件
compiler.plugin('compilation', function (compilation) {
  compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
    // 发布事件
    hotMiddleware.publish({ action: 'reload' })
    cb()
  })
})


// 注册中间件
app.use(devMiddleware)
// 注册中间件
app.use(hotMiddleware)

// 监听 8888端口,开启服务器
app.listen(8888, function (err) {
  if (err) {
    console.log(err)
    return
  }
  console.log('Listening at http://localhost:8888')
})

从上面的代码中可以看到,我们增加了如下代码:

// webpack插件,监听html文件改变事件
compiler.plugin('compilation', function (compilation) {
    compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
        // 发布事件
        hotMiddleware.publish({ action: 'reload' })
        cb()
    })
})

这段代码可能你看不懂,因为这涉及到webpack插件的编写,读者可以参阅下面的连接:

webpack 插件doc1

webpack 插件doc2

我们可以看到,html-webpack-plugin 这个插件的确提供了几个可选的事件,下面也提供了使用方法,这样,我们就能够监听到html文件的变化,然后我们使用下面的代码发布一个事件:

hotMiddleware.publish({ action: 'reload' })

第二步:修改 webpack.dev.conf.js 文件如下:

var HtmlWebpackPlugin = require('html-webpack-plugin')
var path = require('path');
var webpack = require('webpack');
// 引入基本配置
var config = require('./webpack.config');

config.output.publicPath = '/';

config.plugins = [
  // 添加三个插件
  new webpack.optimize.OccurenceOrderPlugin(),
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NoErrorsPlugin(),
  new HtmlWebpackPlugin({
    filename: 'views/shaoxia_demo/index.html',
    template: path.resolve(__dirname, '../views/shaoxia_demo/index.html'), //html模板,绝对路径。
    inject: true
  })
];
// 动态向入口配置中注入 webpack-hot-middleware/client
var devClient = './build/dev-client';
Object.keys(config.entry).forEach(function (name, i) {
  var extras = [devClient]
  config.entry[name] = extras.concat(config.entry[name])
})

module.exports = config;

我们修改了devClient变量,将 ‘webpack-hot-middleware/client’ 替换成 ‘./build/dev-client’,最终会导致,我们入口配置会变成下面这样:

entry: {
    index: [
        './build/dev-client',
         path.resolve(__dirname, '../views/shaoxia_demo/index.js')
    ]
},

第三步:新建 build/dev-client.js 文件,并编辑如下内容:

/**
 * Created by keli on 2016/6/8.
 */
var hotClient = require('webpack-hot-middleware/client')

// 订阅事件,当 event.action === 'reload' 时执行页面刷新
hotClient.subscribe(function (event) {
  if (event.action === 'reload') {
    window.location.reload()
  }
})

这里我们除了引入 ‘webpack-hot-middleware/client’ 之外订阅了一个事件,当 event.action === ‘reload’ 时触发,还记得我们在 dev-server.js 中发布的事件吗:

hotMiddleware.publish({ action: 'reload' })

这样,当我们的html文件改变后,就可以监听的到,最终会执行页面刷新,而不需要我们手动刷新,现在重启服务,去尝试能否对html文件热加载吧。答案是yes。

好了,开发环境终于搞定了,下面我们再来谈一谈生产环境,也就是构建输出,我们现在可以执行一下构建命令,看看输出的内容是什么,为了不必每次都要输入下面这条长命令。

webpack --display-modules --display-chunks --config build/webpack.config.js

我在 shaoxia_demo中新建了一个package.json文件,把命令放要script中。但新建package.json文件的原因并不止是这些。因为还会有其它信息放在这个文件中。例如这次活动项目作者,描述,依赖包,bug提交作途径等。具体请查 node package.json相关介绍。
如下:

{
  "name": "shaoxia_demo",
  "author":"licat",
  "version": "0.0.1",
  "scripts": {
    "dev":"node ../../build/dev-server.js",
    "build": "webpack --display-modules --display-chunks --config ../../build/webpack.config.js"
  }
}

这样,我们就可以通过执行下面命令来进行构建,同时我们还增加了一条开启开发服务器的命令:

// 构建
npm run build
// 开启开发服务器
npm run dev

回过头来,我们执行构建命令: npm run build,查看输出内容。
现在我们只有一个js文件输出了,并没有css文件输出,在生产环境,我们希望css文件生成单独的文件,所以我们要使用 extract-text-webpack-plugin 插件,安装:

npm install extract-text-webpack-plugin --save-dev

然后在build目录下新建 webpack.prod.conf.js 文件,顾名思义,这个使我们区别于开发环境,用于生产环境的配置文件,并编辑一下内容:

var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var path = require('path');
var webpack = require('webpack');
// 引入基本配置
var config = require('./webpack.config');

config.vue = {
  loaders: {
    css: ExtractTextPlugin.extract("css")
  }
};

config.plugins = [
  // 提取css为单文件
   new ExtractTextPlugin("[name].[contenthash].css"),

  new HtmlWebpackPlugin({
    filename: 'index.html',
    template: path.resolve(__dirname, '../views/shaoxia_demo/index.html'), //html模板,绝对路径。
    inject: true
  })
];

module.exports = config;

上面的代码中,我们覆盖了 webpack.config.js 配置文件的 config.plugins 项。
然后修改 package.json 文件中的 script 项为如下:

"scripts": {
    "build": "webpack --display-modules --display-chunks --config ../../build/webpack.prod.conf.js",
    "dev": "node ../../build/dev-server.js"
},

我们使用 webpack.prod.conf.js 为配置去构建,接下来执行:

npm run build

查看你的输出内容,如下图,css文件未提取出来了。
另外我们还可以添加如下插件在我们的 webpack.prod.conf.js 文件中,作为生产环境使用。

new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV: '"production"'
        }
    }),
    // 压缩代码
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    }),
    new webpack.optimize.OccurenceOrderPlugin(),

大家可以搜索这些插件,了解他的作用,这篇文章要介绍的太多,所以我不一一讲解了。

但是

在我们的views下面会有很多个项目。而我们build中的配置路径都是写死的。所以有这样一个需求:
在views中我们新建了项目,随之新建了package.json。我们在package.json的script中定义一个命令。每次执行 npm run 即可进入开发模式,执行 npm run build即可完成打包。

所以

我们需要把build中有关文件路径的都提出来,可以通过命令行输入。为了达到这个目的,我们引入了一个commander 插件,它可以非常方便地从命令行解析参数。

经过改造后有变动的文件如下:
新加的 build/build.js

var webpack= require("webpack");
var program = require('commander');
program
  .version('0.0.1')
  .option('-e, --entry <n> ', '添加入口')
  .option('-op, --outpath <n> ', '输入文件路径')
  .option('-h, --htmltemplate <n> ', 'html模板路径')
  .parse(process.argv);

var config = require('./webpack.prod.conf')(program);

var compiler = webpack(config);

compiler.run(function(err,stats){
  if (err){
    console.log(err);
    return
  }
})

build/dev-server.js

/**
 * Created by keli on 2016/6/8.
 */
// 引入必要的模块
var express = require('express')
var webpack = require('webpack')

var program = require('commander');
program
  .version('0.0.1')
  .option('-e, --entry <n> ', '添加入口')
  .option('-op, --outpath <n> ', '输入文件路径')
  .option('-h, --htmltemplate <n> ', 'html模板路径')
  .parse(process.argv);



var config = require('./webpack.dev.conf')(program);



// 创建一个express实例
var app = express()

// 调用webpack并把配置传递过去
var compiler = webpack(config)

// 使用 webpack-dev-middleware 中间件
var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: config.output.publicPath,
  stats: {
    colors: true,
    chunks: false
  }
})
// 使用 webpack-hot-middleware 中间件
var hotMiddleware = require('webpack-hot-middleware')(compiler)

// webpack插件,监听html文件改变事件
compiler.plugin('compilation', function (compilation) {
  compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
    // 发布事件
    hotMiddleware.publish({ action: 'reload' })
    cb()
  })
})


// 注册中间件
app.use(devMiddleware)
// 注册中间件
app.use(hotMiddleware)

// 监听 8888端口,开启服务器
app.listen(8888, function (err) {
  if (err) {
    console.log(err)
    return
  }
  console.log('Listening at http://localhost:8888')
})

build/webpack.config.js

/**
 * Created by keli on 2016/6/8.
 */
// nodejs 中的path模块
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = function(program){
  var config = {
    // 入口文件,path.resolve()方法,可以结合我们给定的两个参数最后生成绝对路径,最终指向的就是我们的index.js文件
    entry:{
      index:path.resolve(__dirname, '../views/',program.entry)
    },
    // 输出配置
    output: {
      path: path.resolve(__dirname, '../../web/',program.outpath),
      publicPath: '/',
      filename: '[name].[hash].js',
      chunkFilename: '[id].[chunkhash].js'
    },
    resolve: {
      extensions: ['', '.js', '.vue']
    },
    module: {
      loaders: [
        // 使用vue-loader 加载 .vue 结尾的文件
        {
          test: /\.vue$/,
          loader: 'vue'
        },
        {
          test:/\.js$/,
          loader: 'babel?presets=es2015',
          exclude: /node_modules/
        }
      ]
    },
    plugins: [
      new HtmlWebpackPlugin({
        filename: 'index.html',
        template: path.resolve(__dirname, '../views/,',program.htmltemplate), //html模板,绝对路径。
        inject: true
      })
    ]
  }
  return config;
}

build/webpack.dev.conf.js

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

module.exports = function(program){
  // 引入基本配置
  var config = require('./webpack.config')(program);

  config.output.publicPath = '/';

  config.plugins = [
    // 添加三个插件
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new HtmlWebpackPlugin({
      filename: 'views/'+program.htmltemplate,
      template: path.resolve(__dirname, '../views/'+program.htmltemplate), //html模板,绝对路径。
      inject: true
    })
  ];
// 动态向入口配置中注入 webpack-hot-middleware/client
  var devClient = '../../build/dev-client';
  Object.keys(config.entry).forEach(function (name, i) {
    var extras = [devClient]
    config.entry[name] = extras.concat(config.entry[name])
  })
  return config
};

build/webpack.prod.conf.js

var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var path = require('path');
var webpack = require('webpack');

function rtn(program){
  // 引入基本配置
  var config = require('./webpack.config')(program);
  config.vue = {
    loaders: {
      css: ExtractTextPlugin.extract("css")
    }
  };
  config.plugins = [
    // 提取css为单文件
    new ExtractTextPlugin("[name].[contenthash].css"),

    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: path.resolve(__dirname, '../views/',program.htmltemplate), //html模板,绝对路径。
      inject: true
    })
  ];

  return config;
}
module.exports = rtn;

现在,在views下新建一个项目yaha,我们来试验一下build是否可靠。yaha下面包含

1.index.html :入口模板

2.index.js :入口文件

3.package.json :项目信息

其中 package.json 中 的scripts如下


"scripts": {
"build": "node ../../build/build.js -e yaha/index.js --outpath yaha -h yaha/index.html",
"dev": "node ../../build/dev-server.js -e yaha/index.js --outpath yaha -h yaha/index.html"
}

执行 npm run dev 我们发现可以愉快地进入 开发模式了, 执行npm run build 也打包出我们想要的文件了。而我们无需编写webpack.config文件。只需要在package.json换掉一些参数。

参考资料:
HcySunYang
webpack官网

版权声明:本文为博主原创文章,未经博主允许不得转载,如对博文有疑虑请入群454796847交流。 举报

相关文章推荐

vue环境搭建

好文章自己先收藏一下,怕以后找不到。  文章转自:http://www.cnblogs.com/wj204/p/6031435.html 前面vue2.0和webpack都已经有接触了些(vue....

基于webpack和vue.js搭建开发环境(修改文章列子几个小错误)

前言 在对着产品高举中指怒发心中之愤后,真正能够解决问题的是自身上的改变,有句话说的好:你虽然改变不了全世界,但是你有机会改变你自己。秉承着“不听老人言,吃亏在眼前”的优良作风,我还是决定玩火自焚。...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

使用vue+webpack的多页面框子

首先,要大概知道webpack是什么,webpack的插件都是做什么用的,vue是什么,然后看完之后也可以去补充一下这些方面的知识。第一步:安装环境需要安装的有: nodejs,并添加入环境变量PAT...

webpack+vue创建简单项目

-- 安装nodejs 用命令行生成vue项目框架需要npm包管理器来安装,而npm又是在安装nodejs的时候同时安装的, 所以首先要安装nodejs,学习vue有必要了解下nodejs和npm...

使用webpack打包vue工程

最近在研究vue.js,在react中使用的webpack,vue的官网安装的demo工程默认就可以创建webpack的依赖。 下面地址可以安装https://cn.vuejs.org/v2/...

webpack.config.js 参数详解

webpack.config.js文件通常放在项目的根目录中,它本身也是一个标准的Commonjs规范的模块。var webpack = require('webpack'); module.expo...

webpack入门(一)——webpack 介绍

如今的网站正在演化为web应用程序: 1. 越来越多的使用JavaScript。 2. 现代浏览器提供更广泛的接口。 3. 整页刷新的情况越来越少,甚至更多代码在同一个页面。(SPA)因此有很多...

vue环境搭建

好文章自己先收藏一下,怕以后找不到。 文章转自:http://www.cnblogs.com/wj204/p/6031435.html前面vue2.0和webpack都已经有接触了些(vue.js入...

vue环境搭建,安装css,js,less加载依赖

vue环境搭建,安装css,js,less加载依赖 安装淘宝镜像: npm install -g cnpm --registry=https://registry.npm.ta...

使用vue2.0创建的项目的步骤

1.由于vue项目依赖 node.js npm 需要先安装.   若没有请先安装,请百度 //检查是否有node.js  npm vue win+r   输入cmd  输入node -v  回车 会出...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)