webpack学习

第一次接触webpack是学react的时候,然而被吓跑了,完全理解不了啊。之后学vue,把官方配置文件看了下,vue相关的配置大概了解了,也写了一篇文章。最近看vue-ssr,又被webpack搞懵逼了,下定决心跟着文档走了一遍。本文主要还是以配置文件字段介绍为主,毕竟用的最多还是这些。关于安装什么的就不再介绍了。

1.首先配置文件四大块

1.1入口

入口呢是webpack开始检测文件的起点,用过vue的一般都只有一个入口,main.js,当然这么强悍的工具怎么可能只有这么点功能。你也可以使用多入口。

//单入口
entry:"./main.js"
//多入口数组方式
entry:['main.js'...]
//多入口对象方式
entry:{
    main:'./main.js'
}

多入口两种写法,但是数组方式不利于扩展,推荐使用对象方式。

1.2输出

输出这里就可以配置一堆东西了,一个一个来。

//输出文件的名字 可以自定义名字,也可以使用入口文件的名字只需要写成[name].js即可,你还可以添加hash:[name].[hash].js 
 filename:'bundle.js'
//路径,就是你打包之后的文件放到哪里,这里放到dist目录中,注意,这里没有dist目录是会自动创建的
path:path.resolve(__dirname, 'dist')
//设置公共目录
publicPath:'/dist/'

chunkFilename着重介绍下
首先它在config中可以这么写

//id:表示一个序号,hash不必说,chunkhash:n,这里n可以自己配置,生成n位的hash,name就是文件名,具体下面介绍
 chunkFileName:[id].[hash].[chunkhash:3].[name].js

这个会单独输出一个包,并不会跟filename中的内容打包到一起,比如有些文件你并不想打包到主文件中,或者减轻首页负担,只在引入的时候才加载。
这个时候你只需要在引入文件的时候使用require.ensure来引入你需要的模块,然后config中配置上面的信息就可以了。

require.ensure(['./add'], function(require){
    add = require('./add');
},'name');//这里这个name就会跟上面的[name]同步,不写的话就按照序号来了。

关于library和libraryTarget我也没搞清,就不坑人了。
sourceMapFilename

当你使用sourceMap的时候你可以配置你的输出文件名,就是这个参数
sourceMapFilename:'[file].[id].[hash].map'

1.3module

module中主要是各种loader的配置(loader是对不同文件处理的东西)

module:{
    //这里是个数组
    rules:[
        {
          //test是匹配文件的正则表达式
            test:/.js$/,
            //使用loader两种方式,loader或者use
            loader:'babel-loader',
            // use:'babel-loader'
            //这里是做一些额外的配置,比如转es2015
            //options和query是use:[{options}]的代替
            query: {
                presets: ['es2015']
            }
}

1.4plugin

webpack还支持各种插件,来扩展功能,当然你也可以自己写插件,webpack本身自带有一些插件,比如丑化代码。其他的你只需要安装,并new一个实例即可,这个是个数组

plugins:[
    new webpack.optimize.UglifyJsPlugin({
         sourceMap: true,
         compress: {
             warnings: false
         }
     })
]

2.其他重要配置项

2.1devtool

这个很简单,比如你在打包的时候,压缩了代码但为了调试你可以输出sourceMap

dev:'sourceMap'

2.2resolve

这个主要是alias选项,作为优化打包性能,在vue的官方配置中你一定见过下面这个

resolve:{
    alias:{
       'vue$': 'vue/dist/vue.js'
    }
}

这里你可以指定引入文件的别名(vue$)以及具体路径,这样webpack就不用在目录中一层一层的查找。
在resolve中你还可以配置下面两项

aliasFields:['browser'],//默认解析规范
extensions:['.js','.json','.css'],//自动解析确定的扩展

2.3externals

这个主要是防止某些包打入bundle中

3.关于开发

在开发中我们都对其提供的热更新最为感兴趣,我们只需要安装webpack-dev-server,然后我们就可以在config中配置了,也就是devServer,直接看代码了

  devServer:{

    clientLogLevel:"none",
    //提供的内容路径
    // contentBase:path.join(__dirname, "dist"),
    //是否启用gzip压缩
    compress:true,
    //port 在命令行中,端口号,实际在非命令行中也可以使用
    port:9000,
    //output.filename设置bundle.js,惰性模式,每个请求结果都会产生全新的编译,使用filename可以只为某个文件被请求时编译
    //webpack不会监听任何文件改动,只有请求的时候才编译,watchOptions无效,内联模式应该禁用。
    /*lazy: true,
    filename: "bundle.js",*/
    //请求添加首部内容
    headers:{
        'X-Custom-Foo':'bar'
    },
    //任意的404页面可以使用index.html来替换,所以可以直接用localhost:port/index.html来,此时dist目录是个虚拟目录并不会真实的的创建出来,只有webpack命令才会,也就是在build的时候
    historyApiFallback: true,
    //只用在命令行,指定host,如果希望在外部服务器访问,指定host:"0.0.0.0"
    host:"",
    //启用热替换
    // hot:true,
    // hotOnly:true,
    //使用https
    https:true,
    /*https的配置
    * https:{
    *   key:fs.readFileSync(),
    *   cert:fs.readFileSync(),
    *   ca:fs.readFileSync(
    * }
    * */
    //两种模式,默认内联模式(inline),处理时重载的脚本会插入到你的包(bundle)中,并且构建消息会出现到浏览器控制台
    //iframe  inline:false  只在命令行中使用--inline
    //noInfo启用 noInfo 后,诸如「启动时和每次保存之后,那些显示的 webpack 包(bundle)信息」的消息将被隐藏。错误和警告仍然会显示。
    noInfo:false,
    //如果你有单独的后端开发服务器 API,并且希望在同域名下发送 API 请求 ,那么代理某些 URL 会很有用。
    // proxy:{
    //     '/api':"http://localhost:3000"
    // },
    //请求/api/user会代理到http://localhost:3000/api/user
    //如果你不想始终传递 /api ,则需要重写路径:
    /*proxy: {
        "/api": {
            target: "http://localhost:3000",
            pathRewrite: {"^/api" : ""}
        }
    }*/
    //命令行使用,内联模式连接指定服务器。
    // public:{
    //
    // },
    //启动后除了启动信息都不会显示
    /*
    * quit:true,
    * */
    //可以接受一个app对象(express)处理一些请求
    // setup(app){
    //     app.get('/some/path', function(req, res) {
    //         res.json({ custom: 'response' });
    //     });
    // },


}

4node中使用

我们不止可以在命令行中使用,也可以在node中使用,只需要把webpack和配置文件引入即可

var webpack = require('webpack');
var config = require('./webpack.config');
//这里会返回一个compiler对象
let compiler = webpack(config);

使用插件

compiler.apply(new webpack.ProgressPlugin());

compiler对象主要提供两个方法,run和watch

compiler.run(function(err, stats) {
    console.log(stats);
    if(err||stats.hasErrors()){
        //编译错误不在err中
    }
});

watch有两个参数,第一个是配置对象watchOptions,第二个是回调函数handler

watchOptions{
  aggregateTimeout:300,//延迟重新构建时间
   poll:1000,//轮询间隔(多久检测一次)
   ignored:/node_modules/,  //也可以使用anymatch方式 "files/**/*.js",可以忽略检测某些文件
 }

compile.watch()会返回一个watching对象,暴露close(callback)方法,用来结束监听。

我们还可以将编译到内存中,如下

//编译到内存中
const MemoryFS = require("memory-fs");
const webpack = require("webpack");

const fs = new MemoryFS();
const compiler = webpack({ /* options*/ });

compiler.outputFileSystem = fs;
compiler.run((err, stats) => {
    // 之后读取输出:
    const content = fs.readFileSync("...");
});

其实还是有诸多不理解之处,但是对于我们基本的使用,以及看别人的配置还是有一定帮助的。

原文地址:https://www.cnblogs.com/Upton/p/6656875.html