阅读 694
Webpack入门到精通 五(常用配置)

Webpack入门到精通 五(常用配置)

初始化项目

mkdir webpack-config-demo

yarn init -y

yarn add webpack webpack-cli
复制代码

package.json中添加

 "scripts": {
    "build": "webpack"
  },
复制代码
+ src/index.js

const fn = ()=>{
  var a = 100
  var b = 100
  setTimeout(()=>{
    console.log(a + b)
  })
}

fn()
复制代码

运行yarn build,就会看见当前打包好的dist.js文件

image.png

webpack build 支持IE

+ browserslistrc文件

[production]
> 1%
ie 9

[modern]
last 1 chrome version
last 1 firefox version

[ssr]
node 12
复制代码

用babel-loader打包js

babel-loader npm

yarn add -D babel-loader @babel/core @babel/preset-env
复制代码
+ webpack.config.js

module.exports = {
  mode: "production",
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env'],
              ['@babel/preset-react',
                {
                  runtime: 'classic'  //使用经典版
                }
              ]
            ]
          }
        }
      }
    ]
  }
}
复制代码

用babel-laoder打包jsx

yarn add @babel/preset-react
复制代码

use: {
  loader: 'babel-loader',
  options: {
    presets: [
      '@babel/preset-env',
      '@babel/preset-react' //新增
    ]
  }
}
复制代码

测试

src/index.js

import JsxDemo from'./jsx-demo.jsx'

console.log(JsxDemo)
复制代码
+ src/jsx-demo.jsx

const JsxDemo = () => {
  return (
    <div>jsx-demo</div>
  )
}

export default JsxDemo
复制代码

yarn build

image.png

给webpack配置eslint

eslint-config-react-app 此包包含Create React App使用的可共享 ESLint 配置。npm link

yarn add -D 
eslint-config-react-app 
@typescript-eslint/eslint-plugin@^4.0.0 
@typescript-eslint/parser@^4.0.0 
babel-eslint@^10.0.0 
eslint@^7.5.0 
eslint-plugin-flowtype@^5.2.0 
eslint-plugin-import@^2.22.0 
eslint-plugin-jsx-a11y@^6.3.1 
eslint-plugin-react@^7.20.3 
eslint-plugin-react-hooks@^4.0.8
复制代码
+ .eslintrc.js

module.exports = {
  //继承 eslint-config-react-app这个里面包含create react app的eslint配置
  "extends": "react-app",
  rules: {
    // jsx使用 react
    'react/jsx-uses-react': [2],
    // 提示要在 JSX 文件里手动引入 React
    'react/react-in-jsx-scope': [2],
    'no-console': [0]
  },
}
复制代码

webpack可以感知到eslint的配置,从而在编译的过程中提示报错信息

yarn add eslint-webpack-plugin -D
复制代码
webpack/config.js

const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
  // ...
  plugins: [new ESLintPlugin({
    extensions: ['.js', '.jsx']  //不加就不会去检测.jsx文件了
  })],
  // ...
};
复制代码

在没加eslint-webpack-plugin之前虽然我们发现在编辑器中eslint给我们报错了,但是在我们运行yarn build的时候他还是可以编译成功的。如下图

image.png

下面我们来看看加完之后的情况,这个时候,不仅eslint报错了webpack构建的时候也会在控制台报错,这样就很好地使用了eslint

image.png

用babel-loader打包TypeScript

yarn add @babel/preset-typescript -D
复制代码

babel 官网

webpack.config.js

test: /\.[tj]sx?$/,
presets: [['@babel/preset-typescript']]
复制代码

添加一个test.tsx,并且在index.js中引入,以下结果编译成功。

image.png

让eslint支持TypeScript

eslint支持ts,添加相关的配置。

yarn add eslint-config-airbnb-typescript @types/react -D
复制代码
.eslintrc.js
 //覆盖之前的配置(检测ts代码)
  overrides: [{
    files: ['*.ts', '*.tsx'],
    parserOptions: {
      project: './tsconfig.json',
    },
    extends: ['airbnb-typescript'],
    rules: {
      '@typescript-eslint/object-curly-spacing': [0],
      'import/prefer-default-export': [0],
      'no-console': [0],
      'import/extensions': [0]
    }
  }]

复制代码

我们运行yarn build发现此时编译还是可以成功的。 image.png

webpack.config.js 添加'.ts' '.tsx'

plugins: [new ESLintPlugin({
    extensions: ['.js', '.jsx', '.ts', '.tsx']  //不加就不会去检测.jsx文件了
})],
复制代码

修改之后的效果

image.png

用babel-loader打包tsx

生成tsconfig.json文件。

npx tsc --init
复制代码
{
 "jsx": "react", // Specify JS
 "strict": false, // 关闭严格模式  
  "noImplicitAny": true,  //没有隐式的any
}
复制代码

同样我们编写tsx-demo.tsx文件在index.js中引入进行测试。

CRLF 是什么?

一、LF和CRLF是什么

  • CRLF 是 carriage return line feed 的缩写,中文意思是回车换行。
  • LF 是 line feed 的缩写,中文意思也是换行。
  • 它们都是文本换行的方式。

二、LF和CRLF区别

  • CRLF: "\r\n", windows系统环境下的换行方式
  • LF: "\n", Linux系统环境下的换行方式

让js和ts支持@alias

js 支持
webpack.config.js

const path = require('path')
resolve: {
    alias: {
      '@': path.join(__dirname, './src/')
    }
  },
复制代码
ts 支持
tsconfig.json 添加
"compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
}
复制代码

引入代码测试

让webpack支持scss

sass-loader npm

yarn add sass-loader sass style-loader css-loader -D
复制代码
module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        //执行顺序从右到左
        use: [
          // Creates `style` nodes from JS strings
          "style-loader",
          // Translates CSS into CommonJS
          "css-loader",
          // Compiles Sass to CSS
          "sass-loader",
        ],
      },
    ],
  },
};
复制代码

scss自动import全局文件

{
    test: /\.s[ac]ss$/i,
    use: [
      // Creates `style` nodes from JS strings
      "style-loader",
      // Translates CSS into CommonJS
      "css-loader",
      // Compiles Sass to CSS
      {
        loader: "sass-loader",
        options: {
          //需要添加的字符串
          additionalData: `
          @import '@/var.scss';
          `,
          sassOptions: {
            includePaths: [__dirname]  //基于当前目录
          },
        },
      },
    ],
  },
复制代码

scss分享变量给js

可以让项目中用到的css变量用同一份jsscss共同维护一份变量。

+ scss-export.scss

:export {
  border-color: $body-color;
}
复制代码
index.js

import vars from './scss-export.scss';

console.log(vars)
复制代码

image.png

webpack支持less文件

less-loader npm

yarn add less less-loader -D
复制代码
@import './_var.less';

body{
  color: @color;
}
复制代码
webpack.config.js

{
    test: /\.less$/i,
    use: [
      {
        loader: "style-loader",
      },
      {
        loader: "css-loader",
        options: {
          modules: {
            compileType: 'icss',
          },
        },
      },
      {
        loader: "less-loader",
        options: {
          additionalData: `
                @import './_var.less';
              `
        },
      },
    ],
  },
复制代码

less分享给js

_var.less

@color: pink;

:export{
  color: @color;
}
复制代码
index.js

import vars from './_var.less';

console.log(vars)
复制代码

对比scss 和less

要选的话就选scss

stylus文件

stylus npm

style.stylus

color = black;

//变量分享给js

:export{
  color: color
}
复制代码
yarn add stylus stylus-loader -D
复制代码
webpack.config.js
{
    test: /\.styl$/,
    use: [
      {
        loader: "style-loader",
      },
      {
        loader: "css-loader",
        options: {
          modules: {
            compileType: 'icss',
          },
        }
      },
      {
        loader: "stylus-loader",
        options: {
          stylusOptions: {
            import: [path.resolve(__dirname, "src/_var.styl")]
          }
        }
      }
    ]
}
复制代码

webpack config 重构

webpack.config.js

const cssLoaders = (...loaders) => [
  // Creates `style` nodes from JS strings
  "style-loader",
  // Translates CSS into CommonJS
  {
    loader: 'css-loader',
    options: {
      modules: {
        compileType: 'icss',
      },
    },
  },
  ...loaders
]
复制代码

生产页面单独提取css文件

mini-css-extract-plugin webpack文档

yarn add mini-css-extract-plugin -D
复制代码
webpack.config.js

const cssLoaders = (...loaders) => [
  // Creates `style` nodes from JS strings
  mode === 'production' ? MiniCssExtractPlugin.loader : "style-loader",
  // Translates CSS into CommonJS
  {
    loader: 'css-loader',
    options: {
      modules: {
        compileType: 'icss',
      },
    },
  },
  ...loaders
]

plugins: [
    new ESLintPlugin({
      extensions: ['.js', '.jsx', '.ts', '.tsx']  //不加就不会去检测.jsx文件了
    }),
    mode === 'production' && new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css'
    }),
].filter(Boolean)

复制代码

自动生成HTML页面

html-webpack-plugin npm

yarn add html-webpack-plugin -D
复制代码
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: 'index.js',
  output: {
    filename: '[name].[contenthash].js'
  },
  plugins: [
    new HtmlWebpackPlugin()
  ]
}
复制代码

webpack优化 单独打包runtime

optimization: {
    runtimeChunk: 'single',  //运行时文件单独打包
},
复制代码

为什么要单独打包runtime

  • runtime里面的文件是webpack为了运行main.js文件所要依赖的文件。
  • 如果不单独打包,如果我们修改了webpack的配置之后mian.js里面的内容就会发生变化,用户的缓存就会失效,如果单独打包的话当修改完webpack的配置之后只,如果我们没有改变main.js里面的内容的话,就不会重新打包main.js的内容,这样就可以节省宽带,提高用户访问页面的速度。

webpack优化 用splitChunks将node依赖单独打包

在编译的时候要缓存React等类库文件。

webpack优化 固定modules

webpack.config.js

optimization: {
moduleIds: 'deterministic',
runtimeChunk: 'single',  //运行时文件单独打包
splitChunks: {
  cacheGroups: {
    vendor: {
      priority: 10,
      minSize: 0, /* 如果不写 0,由于 React 文件尺寸太小,会直接跳过 */
      test: /[\\/]node_modules[\\/]/, // 为了匹配 /node_modules/ 或 \node_modules\
      name: 'vendors', // 文件名
      chunks: 'all',  // all 表示同步加载和异步加载,async 表示异步加载,initial 表示同步加载
      // 这三行的整体意思就是把两种加载方式的来自 node_modules 目录的文件打包为 vendors.xxx.js
      // 其中 vendors 是第三方的意思
    }
  },
},
},
复制代码

之后再运行yarn build可以看见引入了三个js文件

image.png

optimizationmoduleids

webpack 多页面

webpack.config.js

entry: {
    main: './src/index.js',
    admin: './src/admin.js'
},
plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      chunks: ['main']
    }),
    new HtmlWebpackPlugin({
      filename: 'admin.html',
      chunks: ['admin']
    })
]
复制代码

image.png

webpack优化 common插件

如果共有的文件就打包成一个文件,如果两个入口都同时引用了一个文件,

 optimization: {
    runtimeChunk: 'single',  //运行时文件单独打包
    splitChunks: {
      cacheGroups: {
        common: {
          priority: 5,
          minSize: 0,
          minChunks: 2, //同一个文件至少被多少个入口引用了
          chunks: 'all',
          name: 'common'
        }
      },
    },
  },
复制代码
  1. runtime 为了运行mian.js所要提供的代码。
  2. node_modules venders 全局的
  3. common模块间的 admin.js 和 index.js
  4. self自身的

看这个打包之后页面引入js的顺序

image.png

无限多页面的实现思路

webpack.config.js

let entry = {}
let outputHtml = []

var pages = fs.readdirSync(path.resolve(__dirname, pagesDir))
pages.forEach((item)=>{
  let name = item.replace('.js', '')
  entry[name] = `${pagesDir}${item}`
  outputHtml.push(new HtmlWebpackPlugin({
    filename: `${name}.html`,
    chunks: [name]
  }))
})
复制代码

image.png 只需要把这两个参数弄成动态生成的即可满足要求。测试之后大功告成!!!

最后附上源代码连接 github 码云

系列文章

Webpack入门到精通 一(AST、Babel、依赖)

Webpack入门到精通 二(核心原理)

Webpack入门到精通 三(Loader原理)

Webpack入门到精通 四(Plugin原理)

Webpack入门到精通 五(常用配置)

文章分类
前端
文章标签