webpack 安装
- 安装本地的 webpack 
- webpack webpack-cli -D 
webpack可以进行)配置
手动配置webpack
- webpack.config.js 默认使用 这个配置文件 
- 
npx webpack --config webpack.config.my.js 使用自己的 文件 "script":{ "build":"npx webpack --config webpack.config.my.js"} 
命令太长 可以在package.json 中加入 上面命令
开发服务器配置
-cnpm install webpack-dev-server
webpack.config.js
    devServer: {
        port: 3000, // 端口
        progress: true,//进度条
        contentBase: './build', // 静态服务目录
        compress:true,//启动压缩
    },
自动打包 html
-cnpm install html-webpack-plugin
webpack.config.js
    let HtmlWebpackPlugin = require('html-webpack-plugin')
    plugins:[//数组放着所有的 webpack 插件
        new HtmlWebpackPlugin({
            template:'./src/index.html', //模板位置
            filename:'index.html',//打包文件目录
            minify:{
                collapseInlineTagWhitespace:true,//代码一行显示
                removeAttributeQuotes:true,//去除双引号
            },
            hash:true,//加上hash串
        })
    ]
css 处理器
cnpm install css-loader style-loader sass-loader node-sass less-loader -D
//css-loader 负责解析@import这种语法的
//style-loader 他是把css插入到head的标签中
// loader 的特点 希望单一
// loader的用法 字符串只用一个loader
// 多个loader 需要 []
// loader 的顺序,默认是从右向左执行
// {test:/\.css$/,use:['style-loader','css-loader']}
// 可以处理less文件
webpack.config.js
    {
        test: /\.css$/, use: [
            {
                loader: 'style-loader'
            },
            'css-loader',
            'less-loader'
        ]
    }
######## css 抽离文件
cnpm install mini-css-extract-pllugin -D css 抽离文件
let MiniCssExtractPlugin = require('mini-css-extract-plugin')
let MiniCssExtractPlugin1 = require('mini-css-extract-plugin')
let MiniCssExtractPlugin2 = require('mini-css-extract-plugin')
如果需要打包多个css 文件 那么创建多个
webpack.config.js
    plugins: [//数组放着所有的 webpack 插件
        new MiniCssExtractPlugin({
            filename:'index.css'
        }),
        new MiniCssExtractPlugin1({
            filename:'index1.css'
        })
    ]
    {
        test: /\.scss$/,
        use: [
            MiniCssExtractPlugin.loader, 需要抽离的文件就加上MiniCssExtractPlugin.loader 去掉 style-loader
            'css-loader',
            'sass-loader'
        ]
    }
######## css 自动添加前缀
cnpm install postcss-loader autoprefixer
autoprefixer 插件需要 postcss-loader 处理
postcss-loader 需要房子最后
webpack.config.js
    {
        test: /\.scss$/,
        use: [
            MiniCssExtractPlugin.loader,
            'css-loader',
            'sass-loader',
            'postcss-loader',
        ]
    }
需要创建一个 postcss.config.js 在根目录下
    module.exports = {
        plugins: {
            'autoprefixer': { browsers: 'last 5 version' }
        } 
    }
需要在package.json 加上 browserslist 属性 如果 不配置 package.json 那么就需要创建 .browserslistrc文件
package.json
    "browserslist": [
        "defaults",
        "not ie < 11",
        "last 2 versions",
        "> 1%",
        "iOS 7",
        "last 3 iOS versions"
    ]
.browserslistrc
    # Browsers that we support
    last 1 version
    > 1%
    maintained node versions
    not dead
optimize-css-assets-webpack-plugin 压缩css
cnpm install optimize-css-assets-webpack-plugin -D
webpack.config.js
    压缩在 mode: 'production' 生效 需配置
    let OptimizeCss = require('optimize-css-assets-webpack-plugin')
    optimization:{
        minimizer:[
            new OptimizeCss()
        ]
    }
    只这样配置后 js 不在 压缩 css 压缩
    就需要 安装 uglifyjs-webpack-plugin
    cnpm install uglifyjs-webpack-plugin -D 这个插件
    let UglifyjsPlugin = require('uglifyjs-webpack-plugin')
    optimization:{
    minimizer:[
        new OptimizeCss(),
        new UglifyjsPlugin({
            cache:true, //缓存
            parallel:true, //并发
            sourceMap:true
        })
    ]
},
es6转es5
cnpm install babel-loader @babel/core @babel/preset-env -D
webpack.config.js
{
    test:/\.js$/,
    use:{
        loader:'babel-loader',
        options:{
            presets:[ // 用babel-loader 需要把 es6 -> es5
                '@babel/preset-env'
            ],
        }
    }
}
使用 class
因为class 属于 es7 需要单独安装插件
cnpm install @babel/plugin-proposal-class-properties -D
webpack.config.js
{
    test:/\.js$/,
    use:{
        loader:'babel-loader',
        options:{
            presets:[ // 用babel-loader 需要把 es6 -> es5
                '@babel/preset-env'
            ],
            plugins:[
                '@babel/plugin-proposal-class-properties'
            ]
        }
    }
}
js处理语法及校验
cnpm install --save-dev @babel/plugin-transform-runtime
cnpm install --save @babell/runtime
cnpm install --save @babell/polify
{
    test:/\.js$/,
    use:{
        loader:'babel-loader',
        options:{
            presets:[ // 用babel-loader 需要把 es6 -> es5
                '@babel/preset-env'
            ],
            plugins:[
                '@babel/plugin-proposal-class-properties',
                "@babel/plugin-transform-runtime"
            ]
        }
    },
    include:path.resolve(__dirname,'src'),
    exclude:/node_modules/
}
全局变量引入问题
expose-loader 暴露 全局的loader 内联的 loader
pre 前面执行的loader
normal 普通loader
expose-loader  内联的 loader
postloader  后置的loader
jquery 把它暴露成 $
写法一
import $ from 'expose-loader!Jquery'
写法二
{
    test:require.resolve('jquery'),
    use:'expose-loader?$'
}
写法三  在每个模块里面引入 windos.$ 取不到的
let webpack = require("webpack")
在插件里面使用 
new webpack.ProvidePlugin({
    $:'jquery'
})
cdn 引入的 jquery 然后就不用打包了,配置 external
webpack.config.js
external:{
    jquery:'$'
}
webpack打包我们的图片
1 在js 中创建 图片来引入
cnpm install file-loader 默认会在内部生成一张图片 到build 目录下 把生成的名字返回来
import logo from './logo.png' 把图片引入,返回的结果是新的图片地址
在css中 使用 背景图 css-loader 可以自己转换成 require(....)
requir('./logo.png)
2 html 中直接引入 img
cnpm install html-withimg-loader -D
    {
        test:/\.html/,
        use:'html-withimg-loader'
    }
3 url-loader 替换 file-loader 做一个限制当我们的图片 小于多少 K 的时候 用来转换 base64 来转换
不同位置的 图片 可以配置不同的输出 路径 在options 配置outputPath:'img/'
cnpm install url-loader -D
{
    test:/\.(png|jpg|gif)$/,
    // 做一个限制当我们的图片 小于多少 K 的时候 用来转换 base64 来转换
    use:{
        loader:'url-loader',
        options:{
            limit:200*1024,
            outputPath:'img/'
        }
    },
}
统一加路径
output: {
    filename: 'bundle.[hash:8].js', //打包后的文件名 加上随机hash串 防止出现缓存 只显示8位
    path: path.resolve(__dirname, 'build') // 路径必须是一个绝对路径
    publicPath:'http://www.baidu.com/' //统一加路径
},
如果只给图片加统一路径
{
    test:/\.(png|jpg|gif)$/,
    // 做一个限制当我们的图片 小于多少 K 的时候 用来转换 base64 来转换
    use:{
        loader:'url-loader',
        options:{
            limit:200*1024,
            outputPath:'/img/' //统一加路径
            publicPath:'http://www.baidu.com/' //统一加路径
        }
    }
打包多应用
entry:{
    home:'./src/index.js',
    other:'./src/a.js'
}
// [name]代表了index 和 a
output:{
    filename:'[name].js',
    path:path.resolve(__dirname,"dist")
}
// 打包多个html  不加 chunks 则所有的js 都会被打包到 html里面,加上chunks 则 对应的html只加载 chunks数组里面的 js 
plugins: [
    new HtmlWebpackPlugin({
        template: './src/index.html', //模板位置
        filename: 'index.html',//打包文件目录
        chunks:['index','a']
    }),
    new HtmlWebpackPlugin({
        template: './src/index.html', //模板位置
        filename: 'main.html',//打包文件目录
        chunks:['index']
    }),
]
source-map
1.源码映射 会单独生成一个 sourcemap文件, 出错了 会标识当前报错的行和列大而全
devtool:'source-map',//增加映射文件 可以帮我们 调试源代码
2.devtool:'eval-source-map',//增加映射文件 可以帮我们 调试源代码 显示行和列不会产生单独的文件
3.devtool:'cheap-module-source-map',//会产生一个单独文件 不会产生列
4.devtool:'cheap-module-eval-source-map',//不会产生文件 集成在打包后的文件中,不会产生列
watch 的用法
实时打包
module.exports = {
    watch: true,
    watchOptions: { //监控的选项
        poll:1000, // 每秒问我1000次
        aggregateTimeout:500, //防抖 我一直输入代码
        ignored:'/node_modules/'
    },
}
webpack 小插件应用
1 cleanWebpackPlugin
清除 打包文件 防止打包文件一直存在
cnpm install clean-webpack-plugin -D
let { CleanWebpackPlugin } = require('clean-webpack-plugin')
plugins:[new CleanWebpackPlugin()]
2 copyWebpackPlugin
希望拷贝某个文件到打包文件目录下
cnpm install copy-webpack-plugin -D
let CopyWebpackPlugin = require('copy-webpack-plugin')
    new CopyWebpackPlugin(
        {
            patterns: [
                { from: 'doc', to: 'build' }]
                // 把 doc 文件拷贝到 build 目录下 并且重命名为 build
        }
    )
3 bannerPlugin  内置的 版权声明 每个打包文件都会 插入声明
new webpack.BannerPlugin('make 2019 by ........')
webpack 跨域问题
devServer:{
// 方法1 请求后台接口
proxy:{
    '/api':{
        target:'http://localhost:3000', // 代理地址
        pathRewrite:{
            '/api':'' // 把/api替换为空
        }
    }
}
}
resolve 属性的配置
引入 import 'bootstrap' 默认引的是 js 所以得配上别名
resolve:{ // 解析第三方包 common
    modules:[path.resolve('node_modules)],
    mainFields:['style','main'],//先找 style 在找main
    // mainFiles:[], 先查找的 入口文件 默认是 index
    alias:{
        bootstrap:'bootstrap/dist/css/bootstrap.css'
    },
    extensions:['.js','.css','.jsob'] // 不加后缀名 自动查找 从左往右加
}
环境变量 判断 开发环境 还是线上环境
webpack 自带的 webpack.DefinePlugin({
    DEV:JSON.stringify('dev') // 因为这里需要一个 字符串 “'dev'” 这样不好写
})
由于 不能总是 主动更换开发环境
所以创建 三个 js
webpack.base.js 放公共配置
webpack.dev.js  开发配置
webpack.prod.js 生产配置
dev
let {smart} = require('webpack-merge')
let base = require('./webpack.base.js')
module.exports = smart(base,{
    mode:'dev',
    devServer:{
    },
})
product
let {smart} = require('webpack-merge')
let base = require('./webpack.base.js')
module.exports = smart(base,{
    mode:'product',
    devServer:{
    },
})
安装额 cnpm install webpack-merge -D
########## webpack 优化
noParse exclude include
module:{
  noParse:/juqery/  // 不去解析jquery 种的依赖项
rules:[
    {
        test:/\.js$/,
        exclude:/node_modules/, // 匹配的时候排除 node——modules 目录
        include:path.resolve('src) // 匹配的时候只查 src目录
    }
]
}
忽略插件内部一些多余的插件
new webpack.IgnorePlugin(/\.\/locale/,/moment/) 忽略moment这个组件中的 /locale\ 这个依赖
// 使用时间插件
momet.locale('zh-cn)
由于 上面忽略了,可以手动引入
import 'moment/locale/zh-cn
动态链接库 抽离第三方库
比如说 react react-dom 都是第三方库
创建 webpack.config.react.js
output: {
    // filename: 'bundle.[hash:8].js', //打包后的文件名 加上随机hash串 防止出现缓存 只显示8位
    filename:'_dll_[name].js',//产生的文件名
    path: path.resolve(__dirname, 'build'), // 路径必须是一个绝对路径
    // publicPath:'http://www.baidu.com/' //统一加路径
    library:'_dll_[name]'
},
new webpack.DllPlugin({
    // name == libraray
    name:'_dll_[name]',
    path:path.resolve(__dirname,'dist','manifest.json')
}),
模块happypack 可以实现多线程打包
cnpm install happypack -D
rules 里面 use属性 use: 'Happypack/loader?id=js' 这里的 ID 和 Happypack 插件里面的 ID 是匹配的
let Happypack = require('happypack)
{
    test: /\.js$/,
    use: 'Happypack/loader?id=js'
},
new Happypack({
    id:'js',
    use: {
        loader: 'babel-loader',
        options: {
            presets: [ // 用babel-loader 需要把 es6 -> es5
                '@babel/preset-env'
            ],
            plugins: [
                '@babel/plugin-proposal-class-properties',
                "@babel/plugin-transform-runtime"
            ]
        }
    },
})
webpack 自带优化
1.使用 import 引入的代码在生产环境下,会自动去除没有调用的代码
2.tree-shaking 把没有用到的代码 自动删除掉
let cals = require(demo.js)
calc.default.sun()
// es6 模块会把结果放到 default 这个属性上
所以
scope hosting 作用域提升
let a = 1
let b = 1
let c = 1
let d = a + b + c webpack中可以自动省略,可以简化的代码
抽取公共代码
optimization:{
splitChunks:{ // 分割代码块
  cacheGroups:{
      // 缓存组
      common:{ //公共的模块
          chunks:'initial',
          miniSize:0,
          minChunks:2  //最少使用次数
      },
      vendor:{
          priority:1,// 权重 防止在抽取公共js 的时候再次抽取
            test:/node_modules/,
            chunks:'initial',
            miniSize:0,
            minChunks:2 
      }
  }
}
}
entry: {
index:‘./src/index.js’
other:‘./src/other.js’
},
output: {
    filename:'[name].js',//产生的文件名
    path: path.resolve(__dirname, 'build')
},
webpack 热更新
        port: 3000, // 端口
        progress: true,//进度条
        contentBase: './build', // 静态服务目录
        compress: true,//启动压缩
        hot:true,
    },
    new webpack.NamedModulesPlugin() //打更新的模块目录
    name webpack.HoutMoudleReplacementPlugin() // 热更新插件