生产环境与开发环境的不同
相比于开发环境,生产环境需要额外考虑以下几个方面:
- 样式文件需要单独抽取
- css 兼容性处理
- css / js / html 文件压缩
- js 风格检查
- js 兼容性处理
一个典型的生产环境配置如下
const {resolve} = require('path') // path 属于 node.js 的自带模块const MiniCssExtractPlugin = require('mini-css-extract-plugin')const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')const HtmlWebpackPlugin = require('html-webpack-plugin')// 定义node.js的环境变量,决定使用browserslist的哪个环境process.env.NODE_ENV = 'production'const commonCssLoader = [// 这个loader取代style-loader。作用:提取js中的css成单独文件然后通过link加载MiniCssExtractPlugin.loader,// css-loader:将css文件整合到js文件中'css-loader',/*postcss-loader:css兼容性处理:postcss --> 需要安装:postcss-loader postcss-preset-envpostcss需要通过package.json中browserslist里面的配置加载指定的css兼容性样式在package.json中定义browserslist:"browserslist": {// 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development"development": [ // 只需要可以运行即可"last 1 chrome version","last 1 firefox version","last 1 safari version"],// 生产环境。默认是生产环境"production": [ // 需要满足绝大多数浏览器的兼容">0.2%","not dead","not op_mini all"]},*/{loader: 'postcss-loader',options: {postcssOptions: {plugins: [['postcss-preset-env',{ident: "postcss"},],],},},},]module.exports = {entry:'./src/js/index.js',output: {filename: 'js/built.js',path: resolve(__dirname, 'build')},module: {rules:[{test: /\.css/,use: commonCssLoader,},{test: /\.less/,use:[ ...commonCssLoader, 'less-loader']},/*正常来讲,一个文件只能被一个loader处理当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序先执行eslint再执行babel(用enforce)*/{test: /\.js$/,exclude: /node_modules/, // 忽略node_modulesenforce: 'pre', // 优先执行loader: 'eslint-loader',options: {// 自动修复fix: true,},},/*js兼容性处理:需要下载 babel-loader @babel/core1. 基本js兼容性处理 --> @babel/preset-env问题:只能转换基本语法,如promise高级语法不能转换2. 全部js兼容性处理 --> @babel/polyfill问题:只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了3. 需要做兼容性处理的就做:按需加载*/{// 第三种方式:按需加载test: /\.js$/,exclude: /node_modules/,loader: 'babel-loader',options: {// 预设:指示babel做怎样的兼容性处理presets: [['@babel/preset-env', // 基本预设{useBuiltIns: 'usage', // polyfill 按需加载corejs: { version: 3 }, // 指定core-js版本targets: { // 指定兼容到什么版本的浏览器chrome: '60',firefox: '50',ie: '9',safari: '10',edge: '17'},}]],},},{// 图片处理test: /\.(jpg|png|gif)/,loader: 'url-loader',options: {limit: 8 * 1024,name: '[hash:10].[ext]',outputPath: 'imgs',esModule: false, // 关闭url-loader默认使用的es6模块化解析},},{test: /\.html$/,loader: 'html-withimg-loader',// 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)// url-loader esModule:false 保证用commonjs解析},// 处理其他文件{exclude: /\.(js|css|less|html|jpg|png|gif)/,loader: 'file-loader',options: {outputPath: 'media',},},]},plugins: [new MiniCssExtractPlugin({ // 抽取单独的 cssfilename: 'css/built.css'}),// 压缩cssnew OptimizeCssAssetsWebpackPlugin(),new HtmlWebpackPlugin({template: './src/index.html',// 根据template指定的html文件,将打包后的js引入// 压缩html代码minify: {// 移除空格collapseWhitespace: true,// 移除注释removeComments: true,},})],mode: 'production'}
样式文件单独抽取
css-loader 加载样式文件并以字符串的形式存储在js里,开发环境中使用 style-loader ,将js中的样式变成 style 标签插入页面,此种方式会导致:
- js 文件体积过大
- 先加载js,再创建style标签,渲染速度慢
生产环境使用 mini-css-extract-plugin 插件将css单独抽取成一个文件通过 link 方式引入页面,
使用时:
- 安装,引入插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin') - plugin 配置插件初始化
MiniCssExtractPlugin.loader取代style-loadercss 兼容性处理
postcss-loader用来进行 css 兼容性处理,需要安装postcss-loader和postcss-preset-env,css 兼容性和浏览器的版本有关,postcss 需要通过package.json里面的browserslist来指定兼容的浏览器版本// package.json{"browserslist": {// 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development"development": [ // 开发环境,不需要兼容太多"last 1 chrome version","last 1 firefox version","last 1 safari version"],"production": [ // 生产环境,需要兼容大部分常见浏览器">0.2%","not dead","not op_mini all"]},}
postcss-loader可以和css-loader,MiniCssExtractPlugin.loader一起作为处理 css 的组合const commonCssLoader = [// 这个loader取代style-loader。作用:提取js中的css成单独文件然后通过link加载MiniCssExtractPlugin.loader,// css-loader:将css文件整合到js文件中'css-loader',{loader: 'postcss-loader',options: {postcssOptions: {plugins: [['postcss-preset-env',{ident: "postcss"},],],},},},]
html / css / js 文件压缩
html压缩
配置HtmlWebpackPlugin的minifycss 压缩
初始化OptimizeCssAssetsWebpackPluginjs 压缩
mode = production生产环境自动压缩js 风格检查
eslint-loader对 js 进行风格检查,注意忽略node_modules文件夹,而且在加载 js 的时候是最先执行的enforce: prejs 兼容性处理
babel-loader需要配置@babel/preset-env转换基本语法,剩下的高级语法需要配置@babel/polyfill
