webpack从入门到精通

1. package.json 项目清单文件

version //版本号
description  //描述
main  //主程序入口
script  //脚本
dependencies //依赖

2. .babelrc(babel的根配置文件)

3. script脚本

3.1. entry入口

上面的-f是文件名为entry

entry结构如下

dist是打包后生成的目录,也就是你运行npm run entry后生成的entry的压缩文件

在index.html里引入


然后在index.js里写

alert('i am index')

entry可以是:Object、Function、promise、String

3.1.1. entry为Object的情况如下:
//在webpack.config.js文件里

//对象前面的key就是你生成dist目录后对应的文件名
let base = {
  index: './index.js',
  index1: './index1.js'
}

module.exports = {
  entry:base,
   //这里指定了生成的目录前要加'_你上面对应的文件名.js',所以最后输出的dist下的文件是_index.js和_index1.js
  output: {
    filename: '_[name].js'
  }
}

运行

npm run entry

页面弹出'i am index'的弹窗

3.1.2. entry为Function
let base = {
  index: './index.js',
  index1: './index1.js'
}
function fn(){
  return base
}

module.exports = {
  entry:fn,
  output: {
    filename: '_[name].js'
  }
}
3.1.3. entry为promise
function fn(){
  return new Promise((resolve,reject)=>{
    resolve(base)
  })
}

module.exports = {
  entry:fn,
  output: {
    filename: '_[name].js'
  }
}
3.1.4. entry为String
let base = './index.js'

module.exports = {
  entry:base,
  output: {
    filename: '_[name].js'
  }
}

这里要注意如果是字符串dist目录生成的文件名,就会以默认的main开头,所以最后生成的dist目录为_main.js

3.2. output

output: {
  //导出目录
  path: path.resolve(__dirname, 'uuudist'),
  publicPath: "/output/uuudist/", // server-relative
  //包规范格式
  libraryTarget:'umd',
  library: "MyLibrary", 
  //文件名
  chunkFilename:'[chunkhash]_[name].js',
  //hash位数
  hashDigestLength:3,
  //导出文件 
  //hash ==> webpack编译过程
  // chunkhash => webpack对每个文件的hash
  filename: '_[name][chunkhash].js'
}

path用于定义导出目录的名称
你上面的第二个参数字符串就是你打包生成的目录名,你写的uuudist那就会生成一个uuudist的目录

filename:生成的文件名的格式
其中[name]是拿到你entry里面的对象里的key,而[chunkhash]是webpack编译的时候会认为每一个文件都是一个chunk,他会有一个hash算法来标识每一个文件,然后通过hashDigestLength来定义hash取多少位,使用[chunkhash]主要是用来作为时间戳解决缓存问题,要注意每次文件内容的改变会引起hash值的改变,所以文件不会去重是增量的,比如:原来目录下只有一个index1生成的文件


当你改变index1.js里的内容的时候,会重新对你当前dist下的目录重新生成一遍不同hash的文件

//包规范,一般默认使用umd,提供各种兼容模式
libraryTarget:'umd',
//当你写umd的时候就相当于
if(typeof exports === 'object' && typeof module === 'object')
    module.exports = factory();
else if(typeof define === 'function' && define.amd)
    define([], factory);
else if(typeof exports === 'object')
    exports["MyLibrary"] = factory();
else
    root["MyLibrary"] = factory();
library: "MyLibrary", 
//就相当于变量var MyLibrary,
//直接通过MyLibrary就可以拿到你包的导出内容

hash包括 hash和chunkhash

hash是整个webpack编译过程,也就是说你所有的文件都会生成一个同样的hash值
比如:

filename: '[hash]_[name].js'

最后生成的目录里的文件如下:

chunkhash就像前面说的是webpack对每一个文件都有一个自己的hash值

filename: '[chunkhash]_[name].js'

chunkFilename:异步加载的文件名字
publicPath:异步加载文件的路径(前缀)

在index.js里
//异步加载
//第一个参数是依赖,第二个是function,第三个是文件名
require.ensure([],(require)=>{
    require('./index1.js')
},'dynamic')
//当你要使用异步加载文件的时候就需要使用'/output/uuudist/异步加载的文件名'
publicPath: "/output/uuudist/",
//这里的[chunkhash]对应一个hash值,[name]对应你上面异步加载的第三个参数文件名'dynamic'
chunkFilename:'[chunkhash]_[name].js',

通过定义publicPath,和chunkFilename会在output/uuudist目录下生成一个异步加载的文件

3.3. split

实现文件模块化


可以通过require和import实现模块化引入,下面在index.js里引入split.js里的内容

//split.js
console.log('I am a split')
//index.js
console.log('I am index')
import './split.js'
//require('./split')

最后只要引入index.js就能同时打印出I am a split和I am index

3.4. module

module.exports = {
  entry:base,
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  },
  module:{
    rules:[
    // Conditions, Results and nested Rules.
        {
        test: /\.jsx?$/,
        
        exclude: [
          'node_modules'
        ],
        // flags to apply these rules, even if they are overridden (advanced option)

        //webpack1的语法
        // loader: "babel-loader",

        // rule.use是数组形式和rule.loaders是它的别名
        use:[{
           loader: "babel-loader",
        }]
      },
    ]
  }
};

module是一个对象,对象里面是一个rules规则数组,数组里面又是一个对象,他每次都会对文件走一遍rules,先进行test正则匹配看一下这个文件的文件名满足不满足这个正则,满足的话就开始走use这个数组,使用loader,这个loader就是使用babel-loader来转码成浏览器兼容的js,当发现node_modules里面的js的时候就不会用loader去转码,因为node_modules里面的文件都有一个预处理entry==>loaders==>webpack===>output,所以你即使不通过loader来转码,webpack也会去转的

3.5. resolve

resolve.alias用来处理别名,更容易维护

比如你要在

当前目录结构下的index.js里引入test/test/test.js

那么你就要这么写

//index.js
require('./test/test/test.js')

这样如果多个文件里都要使用它的话,你写起来就会很复杂,这时候我们就可以通过resolve里的alias来实现,alias是一个对象,里面是你定义的别名和路径

module.exports = {
  resolve:{
    alias:{
      //这里的路径只能是绝对路径  
      test:path.resolve(__dirname,'test/test/test.js')
    }
  },
  //entry ==> rules ===> webpack ==> output
  module:{
    rules:[
        {
        test: /\.jsx?$/,
        
        exclude: [
          'node_modules'
        ],
        use:[{
           loader: "babel-loader",
        }]
      },
    ]
  }
};

然后你再引入这个test.js只需引入你定义的别名就行

//index.js
require('test')
//就相当于require('./test/test/test.js')

3.6. devtool

通过dectool:'source-map'可以实现在源文件中debugger
比如你在开发的时候在你的源文件index.js里写了一个debugger

//index.js
import test  from 'test';
debugger;
console.log(test());

如果你不在webpack里面写dectool:'source-map'的话,你打包运行后就会发现它是在你打包生成的文件里debugger了



而我们都是希望在我们编写的文件里测试,所以我们就需要加

module.exports = {
  // https://webpack.js.org/configuration/devtool/#devtool
  devtool:'source-map',
  // https://webpack.js.org/configuration/target/#target
};

再次运行,你就会发现确实在我们的源文件中debugger了

3.7. loaders 预处理

module:{
    //entry => loaders ==> webpack ==> output
    rules:[
            {
                test: /\.js[x]?$/,
                exclude: /node_modules/,
                use: {
                  loader:'babel-loader'
                }
            },
            {
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    fallback: "style-loader",
                    use:{
                        loader:'css-loader',
                        options: {
                           sourceMap: true
                        }
                    }
                })
            },
            {
                test: /\.less$/,
                use: ExtractTextPlugin.extract({
                    fallback:'style-loader',
                    use:['css-loader',{
                        loader:'less-loader',
                        options: {
                           sourceMap: true
                        }
                    }]
                })
            },
            {
                test: /\.scss$/,
                use: ExtractTextPlugin.extract({
                    fallback:'style-loader',
                    use:['css-loader',{
                        loader:'sass-loader',
                        options: {
                           sourceMap: true
                        }
                    }]
                })
            },
            {
                test: /\.(png|jpg|jpeg|gif|woff|woff2|ttf|eot|svg|swf)$/,
                use: {
                    loader:'file-loader',
                    options:{
                        name:'[name]_[sha512:hash:base64:7].[ext]'
                    }
                }
            },
            {
                test: /\.html/,
                use:{
                    loader:"html-loader",
                    options:{
                        minimize: false,
                        attrs:false
                    }
                }
            }
    ]
  }

options是对每一个loader进行个性化配置

3.8. plugins

对webpack编译的生命周期做一个hook

module.exports = {
  plugins:[
            new webpack.ProvidePlugin({
                $: 'jquery'
            }),
            new WebpackNotifierPlugin({
                title: 'Webpack 编译成功',
                contentImage: path.resolve(process.cwd(), './img/avatar.jpeg'),
                alwaysNotify: true
            }),
            new ExtractTextPlugin({
                filename: "[name].css",
                disable: false,
                allChunks: true
            }),
            new webpack.optimize.CommonsChunkPlugin({
                name: 'common',
                minChunks: Infinity
            })
  ],
  module:{
    rules:[
            {
                test: /\.js[x]?$/,
                exclude: /node_modules/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    fallback: "style-loader",
                    use:{
                        loader:'css-loader',
                        options: {
                           sourceMap: true
                        }
                    }
                })
            },
            {
                test: /\.less$/,
                use: ExtractTextPlugin.extract({
                    fallback:'style-loader',
                    use:['css-loader',{
                        loader:'less-loader',
                        options: {
                           sourceMap: true
                        }
                    }]
                })
            },
            {
                test: /\.scss$/,
                use: ExtractTextPlugin.extract({
                    fallback:'style-loader',
                    use:['css-loader',{
                        loader:'sass-loader',
                        options: {
                           sourceMap: true
                        }
                    }]
                })
            },
            {
                test: /\.(png|jpg|jpeg|gif|woff|woff2|ttf|eot|svg|swf)$/,
                use: {
                    loader:'file-loader',
                    options:{
                        name:'[name]_[sha512:hash:base64:7].[ext]'
                    }
                }
            },
            {
                test: /\.html/,
                use:{
                    loader:"html-loader",
                    options:{
                        minimize: false,
                        attrs:false
                    }
                }
            }
    ]
  }
};

你可能感兴趣的:(webpack从入门到精通)