webpack4打包工具

664 阅读5分钟

什么是webpack

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle

可以做的事情

代码转换、文件优化、代码分割、模块合并、自动刷新、代码校验、自动发布

需要提前掌握的内容

  • 需要node基础,以及npm的使用
  • 掌握es6语法

主要学习webpack哪些内容

  • webpack常见配置
  • webpack高级配置
  • webpack优化策略
  • ast抽象语法树
  • webpack中的Tapable
  • 掌握webpack流程,手写webpack
  • 手写webpack中常见的loader
  • 手写webpack中常见的plugin

创建文件

mkdir webpack-test && cd webpack-test
mkdir src
touch src/index.js

初始化文件

npm init -y  初始文件(默认的)
npm init 

开始打包

npx webpack

配置webpack.config.js

touch webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    devServer: { // 开发服务器的配置
       contentBase: path.join(__dirname, 'dist'),
       compress: true,
       port: 3000
    },
    mode: 'development', // 模式 默认两种production development
    entry: './src/index.js', //入口
    output: {
        filename: 'bundle.js', //打包后的文件名
        path: path.resolve(__dirname, 'dist'), //路径必须是一个绝对路径
    },
    plugins: [// 数组放着所有的webpack插件
        new HtmlWebpackPlugin({
            template: './src/index.html',
            filename: 'index.html'
        })
    ]
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="root"></div>
    <script src="bundle.js"></script>
</body>
</html>

index.js

var root = document.getElementById("root");
root.innerHTML="你好"

webpack常见配置

npm i webpack webpack-cli -D
npm i html-webpack-plugin -D

使用模板 html

  • html-webpack-plugin 可以指定template模板文件,将会在output目录下,生成html文件,并引入打包后的js.
npm i  html-webpack-plugin -D

webpack-dev-server

  • webpack-dev-server提供了一个简单的Web服务器和实时热更新的能力
npm i webpack-dev-server -D

pagkage.js

{
  "name": "webpack-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.30.0",
    "webpack-cli": "^3.3.0",
    "webpack-dev-server": "^3.3.1"
  }
}

目前的目录

启动项目

npm run dev

浏览器输入http://localhost:3000/

加载样式文件

  • 在src目录下创建一个index.css
body{
    background-color:red;
}
  • 在index.js中引入index.css
require('./index.css');
  • webpack.config.js增加一些参数
module: { //模块
   rules: [ // 规则 css-loader 
   //  style-loader 把css插入到head的标签中
   //  loader的特点: 希望单一
   //  loader的用法: 字符串只用一个loader
   //  多个loader需要[]
   //  loader的顺序 默认是从右向左执行
   //  loader还可以写出对象方式
   {
    test: /\.css$/,
    use: [
      'style-loader',
      'css-loader'
    ]
   },
   ]
}
  • css-loader style-loader
npm i  css-loader style-loader -D
  • 效果如下

加载less(sass,stylus类似)

  • 在src目录下创建一个index.less
body{
    #root{
        border:1px yellow solid;
        color: #000;
    }
}
  • 在index.js中引入index.less
require('./index.css');
  • webpack.config.js增加一些参数
 {
    test: /\.less$/,
    use: [
        {
           loader: 'style-loader',
        },
        'css-loader','less-loader'
    ]
 },
  • less-loader
npm i less less-loader -D
  • 效果如下

提取单独打包css文件

npm i mini-css-extract-plugin -D
  • webpack.config.js增加一些参数
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
 plugins: [ 
        new MiniCssExtractPlugin({
            filename: 'main.css'
        })
    ],
module: { //模块
        use: [
            MiniCssExtractPlugin.loader,
        ]
       },
       {
        test: /\.less$/,
        use: [
            MiniCssExtractPlugin.loader,
        ]
       }
       ]
    }

css3样式自动加前缀

npm i postcss-loader autoprefixer -D
  • 在webpack-test创建postcss.config.js
module.exports = {
    plugins: [require('autoprefixer')]
}
  • webpack.config.js增加一些参数
{
    test: /\.css$/,
    use: [
        {
           loader: 'style-loader',
        //    options: {
        //        insertAt: 'top' //内联样式最高级
        //    }
        },
        'css-loader',
        'postcss-loader'
    ]
    },
    {
    test: /\.less$/,
    use: [
        {
           loader: 'style-loader',
        },
        'css-loader',
        'postcss-loader',
        'less-loader'
    ]
}

转化es6语法

npm i babel-loader @babel/core @babel/preset-env -D
npm i @babel/plugin-proposal-class-properties -D
  • webpack.config.js增加一些参数
rules: [ 
{
test: /\.js$/,
use: {
    loader: 'babel-loader',
    options: { // 用babel-loader 需要把es6-es5
      presets: [
          '@babel/preset-env'
      ],
      plugins: [
        '@babel/plugin-proposal-class-properties'
    ]
    }
}
] 

全局变量引入

npm i jquery -D
npm i expose-loader -D

第一种

  • import $ from 'jquery';
  • webpack.config.js增加一些参数
 rules: [ 
        {
           test: require.resolve('jquery'),
           use: 'expose-loader?$'
        },
]

第二种

  • webpack.config.js增加一些参数
const webpack = require('webpack');
plugins: [ // 数组放着所有的webpack插件
    new webpack.ProvidePlugin({
        $: 'jquery' // 在每个模块中注入$对象
    })
],

引入图片处理

// 1.在js中创建图片来引入
// 2.在css引入backgroud('url')
// 3.<img src="" alt="" />>
npm i file-loader -D
npm i html-withimg-loader -D
  • webpack.config.js增加一些参数
rules: [ 
        {
          test: /\.html$/,
          use: 'html-withimg-loader'
        },
        {
         test: /\.(png|jpg|gif)$/,
         use: 'file-loader'
        },
]
  • 限制图片大小
npm i url-loader -D
  • webpack.config.js增加一些参数
 {
 test: /\.(png|jpg|gif)$/,
 use: {
     loader: 'url-loader',
     options: {
         limit: 200*1024
     }
 }

images和css打包分类

  • webpack.config.js增加一些参数
 plugins: [ // 数组放着所有的webpack插件
    new MiniCssExtractPlugin({
        filename: 'css/main.css'
    }),
],
{
 test: /\.(png|jpg|gif)$/,
 use: {
     loader: 'url-loader',
     options: {
         limit: 1,
         outputPath: '/img/',
         publicPath: 'https://www.baidu.com' // 在图片上加域名
     }
 }

多页面打包

  • 在scr创建一个other.js
console.log("other 一路走好!")
  • webpack.config.js增加一些参数
// 多入口
entry: {
   index: './src/index.js', 
   home: './src/other.js',
},
output: {
    filename: '[name].js', //打包后的文件名
    path: path.resolve(__dirname, 'dist'), //路径必须是一个绝对路径
    // publicPath: 'https://www.baidu.com'
},
plugins: [ // 数组放着所有的webpack插件
    new HtmlWebpackPlugin({
        template: './src/index.html',
        filename: 'index.html',
        chunks: ['index']
    }),
    new HtmlWebpackPlugin({
        template: './src/index.html',
        filename: 'home.html',
        chunks: ['home']
    }),
]

配置source-map调试代码

  • webpack.config.js增加一些参数
output: {
    filename: '[name].js', //打包后的文件名
    path: path.resolve(__dirname, 'dist'), //路径必须是一个绝对路径
    // publicPath: 'https://www.baidu.com'
},
// devtool: 'source-map', // 1.增加映射文件 可以帮我们调试源代码
// devtool: 'eval-source-map', // 2.不会产生单独的文件,但是可以显示行和列
// devtool: 'cheap-module-source-map', // 3.不会产生列,但是是一个单独的映射文件(产生后你可以保留起来)
devtool: 'cheap-module-eval-source-map',// 4.不会长生文件,集成在打包后的文件中不会产生列

watch实时打包

  • webpack.config.js增加一些参数
entry: {
   index: './src/index.js', 
   home: './src/other.js',
},
watch: true,
watchOptions: { // 监控的选项
  poll: 1000, // 每秒问我1000次
  aggregateTimeout: 500, // 防抖
  ignored: /node_modules/ // 不需要进行监控哪个文件
},

常用的小插件

  • 清除dist (clean-webpack-plugin)
  • 拷贝文件(copy-webpack-plugin)
  • 版权注释(bannerPlugin)
npm i clean-webpack-plugin -D
npm i copy-webpack-plugin -D
  • 在webpack-test创建doc文件,里面创建hello.txt
  • webpack.config.js增加一些参数
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
plugins: [ 
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin([
        {from: 'doc', to: './'}
    ]),
    new webpack.BannerPlugin('cl by 2019')
],

webpack跨域问题

npm i express -D
  • 1)webpack代理
  • 在webpack-test目录下创建server.js
let express = require('express');
let app = express();
app.get('/user', (req, res)=> {
    res.json({ name: "xiaolin3333" })
})
app.listen(3000);
  • webpack.config.js配置
 devServer: { // 开发服务器的配置
    // 1)http:proxy
     proxy: {// 重新的方式 把请求代理到express服务器!
        '/api': {
            target: 'http://localhost:3000',
            pathRewrite: {'/api': ''}
        } // 配置了一个代理
     }
    },
  • index.js
let xhr = new XMLHttpRequest();

xhr.open('GET', '/api/user', true);

xhr.onload = function() {
    console.log(xhr.response,);
}

xhr.send();
  • 启动 node server.js && npm run dev
  • 2)前端只想单纯来模拟数据
  • webpack.config.js配置
devServer: { // 开发服务器的配置
    // 2)前端只想单纯来模拟数据
     before(app) { // 提供的方法 钩子
         app.get('/user', (req, res)=> {
             res.json({ name: "xiaolinwww" })
         })
     }
  • index.js
let xhr = new XMLHttpRequest();
xhr.open('GET', '/user', true);

xhr.onload = function() {
    console.log(xhr.response,);
}

xhr.send();
  • 启动 npm run dev
  • 3)有服务端 不想用代理来处理 能不能再服务端中启动webpack端口用服务端口
npm i webpack-dev-middleware -D
  • server.js
let express = require('express');

let app = express();
let webpack = require('webpack');

// 中间件
let middle = require('webpack-dev-middleware');

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

let compiler = webpack(config);

app.use(middle(compiler));

app.get('/user', (req, res)=> {
    res.json({ name: "xiaolin3333-webpack-dev-middleware" })
})

app.listen(3000);
  • index.js
let xhr = new XMLHttpRequest();
xhr.open('GET', '/user', true);

xhr.onload = function() {
    console.log(xhr.response,);
}

xhr.send();

resolve属性的配置

yarn add css-loader style-loader -D
  • index.js
import './style';

style.css

body{
    background-color:green;
    transform: rotate(90deg);
}
  • webpack.config.js配置
resolve: {// 解析第三方包 common
   modules: [path.resolve('node_modules')],
   extensions: ['.js','.css','.vue']
//    alias: { // 别名 vue vue.runtime
//       bootstrap: 'bootstrap/dist/css/bootstrap.css'
//    },
//    mainFields: ['style', 'main']
//    mainFields: [],// 入口文件的名字index.js
},
 module: { //模块
   rules: [ 
       {
          test: /\.css$/,
          use: ['style-loader','css-loader']
       },
    ]
}

项目文件未更新

今天到此结束,明天更新。。。。