精华内容
下载资源
问答
  • vue 多项目 依赖webpack开发共用 配置

    万次阅读 2016-06-08 19:01:57
    由于项目历史遗留问题,项目目录不尽合理。如下 root //其它文件 |–vue_dev // 基于vue开发的 ...……..|—views // 下面会有很多项目 ……..|—utils // 放一些公共的有用的东西 |–web //输

    由于项目历史遗留问题,项目目录不尽合理。如下
    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官网

    展开全文
  • 用于webpack的插件,可在基于纱线和基于webpack项目中删除传递依赖项。 用法 从包中导入 const { WebpackDeduplicationPlugin } = require('webpack-deduplication-plugin'); 并将其添加到您的webpack配置中: ...
  • requirejs 修改为webpack 模块中依赖其他模块时的配置项
  • 可能更的是为了适应一些老用户的需求,我们更过看的是webpackwebpack-simple   创建项目的时候  vue init webpack|webpack-simple 项目名   这里我们应该注意的是两者迁移的时候的一个问题:...

    bogon:~ ericzhang$ vue list

      Available official templates:

        browserify - A full-featured Browserify + vueify setup with hot-reload, linting & unit testing.

        browserify-simple - A simple Browserify + vueify setup for quick prototyping.

        pwa - PWA template for vue-cli based on the webpack template

        simple - The simplest possible Vue setup in a single HTML file

        webpack - A full-featured Webpack + vue-loader setup with hot reload, linting, testing & css extraction.

        webpack-simple - A simple Webpack + vue-loader setup for quick prototyping.

     

     

    nmp I vue-cli -g 装完脚手架之后,调用vue list 我们会发现 vue init 创建的基础工程有上述几种,browserify和browserify-simple 可能更多的是为了适应一些老用户的需求,我们更过看的是webpack和webpack-simple

     

    创建项目的时候 

    vue init webpack|webpack-simple 项目名

     

    这里我们应该注意的是两者迁移的时候的一个问题:

    webpack webpack-simple 从字面意义上看几乎是一致的,像是一个是简化版,另一个是完全版。

    其实不然, webpack-simp le 是基于 Webpack@2 l .0-beta.25 进行配 置的版本,而 webpack 模板则是基于 Webpack ^ 1.3 .2 配置的。这两个版本暂时是互相不兼容的 

     

    所以依赖包的迁移方法是把原有的node_modules里边的依赖包全部删掉,然后npm i 重新添加

     

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 68,678
精华内容 27,471
关键字:

webpack多项目依赖