乐趣区

关于webpack:webpack-安装和配置

webpack 根底篇

npm 卸载包

npm uninstall 包名 npm unistall webpack -g -global 全局示意哪都能用

初始化我的项目

 yarn init -y ||npm init -y

webpack 装置

  • webpack4.0
  • 装置本地的 webpack
  • yarn add webpack webpack-cli -D||npm install webpack webpack-cli -D
  • -D 示意 development 开发环境

webpack 能够进行 0 配置

  • 目录构造

    • src

      • index.js
  • 间接运行 npx webpack
  • 打包工具 -> 输入后的后果(js 模块)
  • 打包(间接 js 的模块化)

手动配置 webpack(0 配置很弱)

  • [x] 默认配置文件的名字是 webpack.config.js/webpackfile.js 通常应用 webpack.config.js
  • webpack 是基于 node 编写的
  • 有 webpack.config.js 运行命令就会走咱们本人写的配置
  • –config 来指定 webpack 运行哪个文件

* 开发服务器配置

- yarn add webpack-dev-server -D||npm install webpack-dev-server -D
devServer:{
  port:3000, #端口号
  contentBase:'./dist', #目录 如果没有 dist 文件夹 会在内存外面主动创立
  open:true, #是否主动关上浏览器
  progress:true, #显示进度条
  compress:true  #是否开启 gzip 压缩
  proxy:{// 能够配置跨域}
 }

* 配置脚本命令 package.json

  • “scripts”: {} 这外面配置的命令叫做脚本
  • — config 指定默认运行文件是哪个
  • “build”: “webpack –config webpack.config.js”, npm run build = npx webpack 会打包
  • “dev”: “webpack-dev-server” npm run dev 会启动一个服务器 默认会关上 localhost:8080
  • “start”:”npm run dev”
  • 这样就能够通过 npm run dev/npm run build 执行相干的命令

* 配置进口入口

  • [x]entry 入口 能够是相对路径
  • [x]output 进口 输入
  • path 输入门路 必须是绝对路径 打包过后的文件夹名称
  • filename: 打包当前的文件名称
module.exports={
  entry:'./src/index.js',
    output:{path:path.resolve(__dirname,'dist'),
      filename:'bundle[hash:6].js',
      publicPath:'http://www.baidu.com'
     }
}

间接给文件加 hash 值(避免浏览器缓存)

filename:'bundle[hash].js'
能够用: 前面跟数字设置 hash 值的长度
filename:'bundle[hash:8].js'

* 配置打包环境

  • mode 的值 2 个值 development 和
    production
  1. [x] development 开发环境 代码没压缩 有正文
  2. [x] production 生产环境 代码压缩 没有正文
module.exports={
  mode:'development',
  ...
}

解决 html 主动引入 js

  • plugin 插件 plugins 插件们 数组[插件 1, 插件 2, 插件 3]
  • src

    • index.js
    • index.html
  • [x] yarn add html-webpack-plugin -D||npm install html-webpack-plugin -D
  • 当有插件的时候须要配置 plugins 插件汇合类型是数组
  • 每一个插件都是通过 new 来调用,例:new HtmlWebpackPlugin()
  • 能够运行 npm run dev/npm run build 查看后果
  • 装完插件后运行 webpack 会主动引入咱们作为入口的 index.js
{
  * template:'./src/index.html',// 应用哪里的 html 做模板
  * filename:'index.html', // 编译后的文件名
  hash:true,// 加 hash 值
  minify:{ // 压缩配置
    removeAttributeQuotes:true, // 去除双引号
    collapseWhitespace: true,  // 折叠去除空格
  }
}

解决款式 在 webpack 外面所有皆模块

  • src

    • index.html 是模板 不倡议在外面引入货色
    • index.js
    • style.css
  • . index.js 通过 require require(‘/style.css’) 报错如下
You may need an appropriate loader to handle this file type
appropriate  适合的
你可能须要一个适合的 loader
在 webpack 会把 js,css,图片都看成模块,每一个模块都须要对应的模块解析器
  • . 配置 module, 配置 rules 数组,示意很多规定,用正在匹配 js、css 等,rules 外面配置不容的 loader, 每个 loader 的配置都是一个对象
module:{rules:[]
}

loader 的配置办法 test 匹配规定 use 应用什么 loader
yarn add css-loader style-loader -D||
npm install css-loader style-loader -D

  • test 示意什么文件应用以后的 loader 用正则配置
  • use 的用法
  1. 字符串 只能写一个 loader
    use:’css-loader’
  2. 数组 能够写多个 loader 数组外面能够放字符串和对象
    css-loader 解析 require/import 语法
    style-loader 把 css 插入到 style 标签中
use:['style-loader','css-loader']
use:[{loader:'style-loader'},'css-loader']

loader 的执行程序是从右到左执行 从下到上

rules:[
 {
     test:'/\.css$/',// 匹配以 css 结尾的文件
     use:[]}
]
  • .use 能够间接写 loader,也能够写成对象,写对象的时候能够进行配置
    options 能够做一些自定义的配置
 {
   loader:'style-loader',
    options:{insertAt:'top'  //css 搁置地位能够决定 css 的优先级}
  • src

    • index.js
    • b.less
    • a.css
  • public

    • index.html
  • 配置 less 编译(less->css) 因为从右向左,从下到上执行 所以写在下边和左边
    npm install less less-loader -D
  • 编译 sass
    npm install node-sass sass-loader -D
  • 编译 stylus
    stylus stylus-loader -D
  {
    test:/\.less$/,
    use:[
       'style-loader',
       'css-loader',
       'less-loader'
    ]
 }

loader 的执行程序

  • 从下到上 从右到左

抽离 css

  • [x] npm install mini-css-extract-plugin -D
  • MiniCssExtractPlugin 插件自带一个 loader
  • MiniCssExtractPlugin.loader 会主动把 css 抽离进去 作为援用的形式引入页面
  new MiniCssExtractPlugin({filename: 'main.css' ## 抽离进去的 css 的文件名})
  • [x] 在 loader 外面的写法
  use: [MiniCssExtractPlugin.loader, "css-loader"]

应用 postcss-loader,autoprefixer 增加浏览器前缀

  • [x] yarn add postcss-loader autoprefixer -D
  • autoprefixer 主动增加浏览器前缀的插件
  • 装置 postcss 插件
    yarn add postcss-preset-env -D 容许应用 css 将来个性的插件
  • [x] 须要配置 postcss 默认文件 名字
    在根目录下创立 postcss.config.js/.postcssrc.js
postcss.config.js
/ 容许你应用将来的 CSS 个性。const postcssPresetEnv = require('postcss-preset-env');
// 主动增加浏览器前缀
const autoprefixer = require('autoprefixer');
module.exports = {
    plugins: [
      postcssPresetEnv,
      autoprefixer({})
    ]
  };
  • 在应用 autoprefixer 做兼容性前缀时,咱们要指定浏览器版本来确定在指定版本中增加兼容性前缀。能够在 package.json 中的 browserslist 字段中指定。或者独自建设一个.browserslistrc 文件
{
  test:/\.less$/,
  use:[
     MiniCssExtractPlugin.loader,
    'css.loader',
    'less-loader',
    'postcss-loader'
  ]
}
  • 放到所有 cssloader 前面,执行程序起因
 npm run dev 的时候会报错
 Error: No PostCSS Config found in: /Users/ruanye/Desktop/project/src
 没有找到 postcss 的默认文件
  • [x] postcss.config.js 文件外面的内容:
 module.exports={plugins:[require('autoprefixer')]
  }

解决 js es6 转化成 es5 (babel)

  • [x] yarn add babel-loader @babel/core @babel/preset-env

@babel/core babel 外围模块
@babel-preset-env 规范语法转化成低级语法

  • presets 预设插件 比方定案的 promise 是不会被转化的
  • yarn add @babel/polyfill 曾经废除
{
  "presets": [
    [
      "@babel/preset-env",
      {"useBuiltIns": "entry"  主动注入依赖}
    ]
  ]
}
  • useBuiltIns 须要依赖 core-js
  • npm install –save core-js@2
  • [x] yarn add @babel/plugin-transform-runtime @babel/runtime
  • @babel/plugin-transform-runtime 是依赖于 @babel/runtime 的
  • @babel/runtime 是生产环境也须要的下载的时候不要加 -D
  • 作用 @babel/plugin-transform-runtime 去除反复代码
    第二种写法
    @babel/plugin-transform-runtime 去注入 core-js
    须要下载 yarn add @babel/runtime-corejs2
 在 runtime 插件里配置 core-js 的益处
 创立一个沙箱坏境(洁净的坏境,代码不受内部的任何影响)

配置须要解析和不须要解析 loader 的文件门路

  • [x] include 蕴含 include:path.resolve(__dirname,’src’),
  • [x] exclude 不蕴含 exclude:/node_modules/
{
       test:/\.js$/,
                use:'babel-loader',
                include:path.resolve(__dirname,'src'),
              exclude:/node_modules/   不去匹配 node_moudle 上面的文件
 }

babel 也能够独立进行配置,文件名字.babelrc

  • 配置的时候 loader 间接写成 use:’babel-loader’, 其余配置写在.babelrc 外面
 {presets:['@babel/preset-env'],
   plugins:[....]
 }
  • 如果 webpack options 对 babel-loader 进行了配置 不须要.babelrc 文件 如果有的就删除

js 语法校验

  • yarn add eslint eslint-loader -D
  • 初始化 eslint 配置文件
npx eslint --init
  • [x] 增加 enforce pre 强制先执行 previous 前置 loader
{
  enforce:'pre',
  test:'/\.js$/',
  loader:'eslint-loader',
}

desServer 下配置项 有报错的时候呈现通明的遮罩层, 个别不配置

desServer{
overlay: true,
...
}

* 配置优化项

  • yarn add optimize-css-assets-webpack-plugin terser-webpack-plugin -D
    optimize: 优化 assets: 资源
    optimize-css-assets-webpack-plugin 压缩 css 的
    terser-webpack-plugin 压缩 js 的 uglify 不反对 es6
optimization: { 优化
    minimizer: [new OptimizeCssAssetsWebpackPlugin({}), new TerserWebpackPlugin({})
    ]
  }
  • mode 改成 production
  • npm run build 打包之后 csss 是压缩过的

第三方模块的应用

  • yarn add jquery
  • yarn add expose-loader -D
  • expose-loader 负责把变量裸露给全局 loader
  1. 内联 loader 的形式配置 根本不应用
  import $ from "expose-loader?$!jquery"
  1. 失常 loader 配置
{test:require.resolve('jquery'),
  loader:"expose-loader?$"
}
  1. 通过 webpack 提供的内置插件
  • 在 plugins 配置,ProvidePlugin webpack 自带插件
  • 自带插件都须要引入 webpcak 模块
  • 在每个模块中注入 $ 对象 不须要引入能够间接应用 $ 这里 window.$ 是 undefined;
let webpack = require('webpack')
...
 new webpack.ProvidePlugin({$:"jquery"})

配置疏忽打包项(次要是引入 cdn 资源的时候)

105 KiB 18.2 KiB

externals:{jquery:"jQuery"}

通过插件引入 cdn 资源(web 前端优化的一种伎俩)

yarn add add-asset-html-cdn-webpack-plugin

new AddAssetHtmlCdnWebpackPlugin(true, {
     jquery: 'https://cdn.bootcss.com/jquery/3.4.1/jquery.js',
     vue: '//cdn.bootcss.com/vue/2.5.16/vue.min.js',
     vueRouter: '//cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js',
 }),

在 webpack 中引入图片的几种形式

  • src

    • index.js
    • style.css
    • b.less
    • index.html
    • logo.png
  • 在 js 中创立图片来引入
  import logo from './logo.png';
   let img = new Image() ;
   img.src = logo
   document.body.appengChild(img)

会在内存外面创立一个新的图片

You may need an appropriate loader to handle this file type
你须要一个适合的 loader 去解决这个文件类型
  • 在 css 引入 background(url)
  • <img src=”/> 须要把图片放到 dist 文件夹

图片解决

yarn add file-loader html-withimg-loader url-loader -D
file-loader

{test:/\.(png,jpg,gif)$/,
  use:'file-loader'
}
  • [x] 在 html 引入图片打包会找不到文件 须要应用 html-withimg-loader 解决打包之后门路不对的问题
{
  test:/\.html$/,
  use:'html-withimg-loader'
}
  • 小图片转化成 base64 => 前端优化
  • [x] 在图片十分小的状况下不心愿走 http 申请,个别状况下不会间接应用 file-loader 通常咱们应用 url-loader
  • 在图片小于多少 k 的时候能够做一个限度,用 base64 来转化,base64 大小会比原来文件大 3 分之 1
  • 1024b = 1kb 1024kb = 1m 1g = 1024m
  • limit 限度图片大小多大以内 转成 base64
  {test:/\.(png,jpg,gif)\$/,
  user:{
  loder:'url-loader',
  options:{limit:10000 示意多少字节 1024 字节是 1kb}
  }
  }
  • url-loader 能够解决 mp4|webm|ogg|mp3|wav|flac|aac
  • url-loder 能够解决各种字体格局 woff2?|eot|ttf|otf
  • file-loader 字体话个别倡议用 file-loader,字体转 64 可能存在无奈辨认 file-loader 就是简略的复制粘贴
{test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {limit: 0,}
      },
      {test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {limit: 0}
      }

* 打包文件分类

  • 图片 loader 的 options 外面增加
 options:{
   limit:1000
   outputPath:'/img/',
   }
  • css 增加在 css 插件外面
 new MiniCssExtractPlugin({filename:'css/main.css'})
  • js 增加到 filename 后面
   filename:'js/main[hash].js',
  • 增加域名 publicPath 的用法
 output: {
   filename: 'bundle.js',
   path: path.resolve(\_\_dirname, 'build'),
   publicPath:'http://www.baidu.cn'
   }
  • 如果只须要图片增加域名
 options:{
  limit:1,
  outputPath:'/img/',
  publicPath:'http://www.baidu.cn'
  }

webpack 配置篇

webpcak 罕用插件

  1. yarn add clean-webpack-plugin -D
    革除缓存插件, 能够写字符串 也能够写成数组
    new CleanWebpackPlugin();

    • 每次主动删除 dist 目录下的所有文件
  2. yarn add copy-webpack-plugin -D
    拷贝插件
    new CopyWebpackPlugin([//
    {from:’img’,to:’./’}
    ]),
  3. 版权插件 webpack 自带插件
    let webpack = require(‘webpack’)
    new webpack.BannerPlugin(‘make 2019 by ry’)

打包多页利用

  • 入口须要配置成对象
entry:{
        home:'./src/index.js'
        other:'./src/other.js'
    }
  • 进口须要多个进口,扭转 filename 的写法
    filename:'[name.js]’
  • 保障 html 页面引入本人对应的 js
    应用 chunks 代码块 来实现
    chunks:[‘home’]
    如果 home 兴许应用 other
    chunks:[‘home’,’other’]
  let pages = [{
    filename:'index.html',
    chunk:'index'
},{
    filename:'login.html',
    chunk:'login'
}].map((item)=>{ // webpack splitChunks 能够配置公共文件的
    return new HtmlWebpackPlugin({ // 配置输入的 html 格局
        filename:item.filename,
        title:'hello',
        minify:{
            removeAttributeQuotesd:true,
            collapseWhitespace:true,
        },
        chunks:[item.chunk], // 设置援用的代码块
        hash:true, // ? 前面的名字
        template:'./public/index.html'
    })
})

配置 soure-map 源码映射

文档地址 :https://webpack.docschina.org…

 devtool:'source-map'
  • source-map 会独自生成一个 sourcemap 文件 能够帮咱们调试源代码 会显示以后报错的列和行
  • eval-source-map 不会产生独自的文件 然而会显示报错的行和列
  • cheap-module-source-map 不会产生列 然而是一个独自的文件
  • cheap-module-eval-source-map 不会产生文件也不会产生列 会间接集成在文件里

实时编译

watch:true

  • 监控的选项
watchOptions:{
    poll:1000  // 每秒问我多少次
    aggreatmentTimeout:500 // 防抖 始终输出代码
    ignored:/node_modules/
}

配置环境变量

node 提供的环境变量:process.env.NODE_ENV
依据 wepack 配置的 mode 值

new webpack.DefinePlugin({
       // 字符串必须要包两层
     'production':JSON.stringify('production'),
 }),

webpack 解决 跨域问题

  • webpack 自带 express
  1. * 代理的形式 重写的形式 把申请代理到 express 服务器上
  • target 拜访 http://localhost:3000 等于拜访 以后服务器上面 ‘/api’
  • pathRewrite 重写门路 /api/user 等于拜访 localhost:3000/user
 devServer:{
 ...
 proxy:{ //
      '/api':{
         target:'http://localhost:3000',
         pathRewrite:{'/api':''}
       }// 配置了一个代理
   }
}
  1. 间接应用 webpack 提供 mock 数据 webpack 自带 express
  • webpack 提供一个办法 before
  • 参数是 app app 就是 let app= express()
   before(app){app.get('/user',(req,res)=>{res.json({name:'leilei'})
       })
    }
  1. 能够间接在 node 的服务端启动 webpack 端口是服务端端口 不在须要 npm run dev 来启动 webpack
  • yarn add webpack-dev-middleware -D
    server.js 批改如下
let webpack = require('webpack');

let middle = require('webpack-dev-middleware');

let config = require('./webpack.config.js');

let compiler = webpack(config);

app.use(middle(compiler));

resolve 用法

extensions 拓展名
alias: 别名 bootstrap:’bootstrap/dist/css/bootstrap.css’
mainFields 能够配置先找哪个入口
mainFiles:入口文件的名字

resolve:{modules:[path.resolve('node_modules')],
    extensions:['.js','.css','.json','.vue'],
    mainFields:['style','main']
    mainFiles:[], // 入口文件的名字 index.js
    alias:{bootstrap:'bootstrap/dist/css/bootstrap.css'}
 }

辨别环境

webpack.config.js 改成 webpack.base.js
新建文件 webpack.prod.js 和 webpack.dev.js

  • 配置开发环境的写法
webpack.dev.js
let {smart} = require('webpack-merge');
let base = require('./webpack.base.js');

module.exports = smart(base,{
   mode: 'development',
   devServer:{ },
   devtool:'source-map'
})
  • 配置生产环境的写法
let {smart} = require('webpack-merge');
let base = require('./webpack.base.js');

module.exports = smart(base,{
   mode: 'production',
   optimization:{minimizer:[]
   },
   plugins:[]})

最新配置计划
package.json 配置

scripts": {"dev":"webpack-dev-server --env.development --config ./build/webpack.config.js","build":"webpack --env.production --config ./build/webpack.config.js"}
let merge = require('webpack-merge');
module.exports = (env) => {console.log(process.env.xxx); // 能够通过 cross-env 来设置环境变量
  if(env.production){
    // 生产环境
    return merge(base,prod);
  }else{return merge(base,dev);
  }
}

webpack 优化

  1. 自带优化 tree-shaking(树的摇摆),主动去除没有应用的代码, 反对生产模式失效

package.json 配置副作用(只对 es6 语法有成果)

  • sideEffects:false 副作用的文件不打包
  • 要应用哪些副作用
    “sideEffects”: [
    “*.css”
    ]
  • 能够用 require (‘./style.css’)来解决副作用不失效的问题

optimization:{
usedExports:true // 在开发中能够看到哪个包 / 办法被应用了,其余的没用的会标示
},

  1. 自带优化 scope-hosting 作用域晋升
let a = 1;
let b= 2;
let c = a+b;
console.log(c);

把变量进行压缩,去提取模块中的导出的变量

  1. noparse
  module: {
   noParse: /jquery/, // 不去解析 jquery 中的依赖库
   ...
   }
  1. 懒加载 import() es6 草案中的语法
    yarn add @babel/plugin-syntax-dynamic-import -D

    • src

      • index.js
      • a.js
  • a.js 内容
export default 1234;
export const b = 3;
  • index.js 内容
let btn = document.createElement('button');
btn.innerHTML = '点击实现异步加载';
btn.addEventListener('click', async function() {
  // 返回的是一个 promise jsonp 原理实现的
  let res = await import('./a');
  console.log(res);
});
document.body.appendChild(btn);
  1. 热更新(浏览器强制刷新叫做硬更新), 热更新就是代码批改之后浏览器不须要刷新 css-loader 自身反对热更新
  • devServer 配置
devServer:{hot:true}
  • plugins 外面配置热更新插件
new webpack.HotModuleReplacementPlugin()
  • 代码外面的写法热更新文件夹外面
  1. IgnorePlugin 疏忽 webpack 内置插件 以 mement 库为例 间接应用会引入所有的语言包 配置疏忽项之后咱们只须要手动引入咱们须要的语言包 打包的时候只打包须要的
  • 配置疏忽项之前打包大小 287kb 配置疏忽项之后打包的大小 – 67.8k
  • index.js 内容
 import moment from 'moment';
 设置语言

 手动引入所须要的语言
 import 'moment/locale/zh-cn'

 moment.locale('zh-cn');
 let r = moment().endOf('day').fromNow();
 console.log(r);
  • 插件写法
new webpack.IgnorePlugin(/\.\/locale/, /moment/)
  1. happypack 能够应用多线程来打包
    yarn add happypack
  • id 通知 happy 打包的时候用哪个 id 对应哪个 loader 进行多线程打包
  • js 多线程打包 扭转 babel-loader 的写法
{
      test: /\.js$/,
      ...
      use: {loader: 'happypack/loader?id=js'}
 }
 new Happypack({
      id:js,
      use:'babel-loader',
   })
  • css 也能够实现多线程打包
    {
      test: /\.css$/,
      use: 'Happypack/loader?id=css'
    }
   new Happypack({
      id: 'css',
      use: ['style-loader', 'css-loader']
    })
  1. 抽离公共代码(多入口)
optimization:{ // commonChunkPlugins
    splitChunks:{ // 宰割代码块
      cacheGroups:{ // 缓存组
        common:{ // 公共的模块
          chunks:'initial',
          minSize:0,
          minChunks:2,
        },
        vendor:{ // 第三方模块
          priority:1, // 权重
          test:/node_modules/, // 把你抽离进去
          chunks: 'initial',
          minSize: 0,
          minChunks: 2
        }
      }
    }
  }

wepack 框架配置 vue 的应用

  • 应用 vue 模板须要写 template
    yarn add vue vue-loader vue-template-compiler
  • vue-loader 解析 vue 文件
  • vue-template-compiler 解析 vue 中的 template
  1. 配置扩展名和别名
- https://cn.vuejs.org/v2/guide/installation.html#%E5%AF%B9%E4%B8%8D%E5%90%8C%E6%9E%84%E5%BB%BA%E7%89%88%E6%9C%AC%E7%9A%84%E8%A7%A3%E9%87%8A
  resolve:{extensions: ['.js','.vue','.json'],
  alias: { // 开发环境应用 vue.esm.js
  'vue\$': 'vue/dist/vue.esm.js', // 退出这句话
  }
  },
  1. vue-loader 须要应用 vueLoaderPlugin 插件
const VueLoaderPlugin = require('vue-loader/lib/plugin')
 plugins: [new VueLoaderPlugin()
   ]
 }
  1. 配置 loader 解析 vue 文件
   module.exports = {
   module: {
   rules: [
   ...
   {
   test: /\.vue$/,
   loader: 'vue-loader'
   }
   ]
   },

VueLoaderPlugin 这个插件的职责是将你定义过的其它规定复制并利用到 .vue 文件里相应语言的块。例如,如果你有一条匹配 /.js&dollar;/ 的规定,那么它会利用到 .vue 文件里的 <script> 块。

当初咱们就能够依照 vue 模板的模式来编写代码了。
4. 解决 vue 外面款式的问题 yarn add vue-style-loader

odule.exports = {
 // other options...
 module: {
  rules: [
   {
    test: /\.vue$/,
    loader: 'vue-loader',
    options: {
     loaders: {
      css: ExtractTextPlugin.extract({
       use: 'css-loader',
       fallback: 'vue-style-loader' // 这是 vue-loader 的依赖
      })
     }
    }
   }
  ]
<template>
    <div class="divWrap"></div>
</template>
<script>
export default {data(){return {}
    },
    created(){},
    methods:{}}
</script>
<style scoped>
.divWrap{}
</style>
退出移动版