webpack 生产环境打包【实践】

上一篇博客:开发环境打包

实践后加深的理解

  • 开发环境(devlopment):能让代码本地调试运行的环境。
  • 生产环境(production):能让代码优化上线运行的环境。
  • 生产环境包的构建:为了让代码能在生产环境表现的更加优秀,构建时除需要关注代码普通的编译打包功能之外,还需要关注代码的浏览器兼容以及运行速度等相关问题。

实践结果

package.json

{
    
    
  "name": "webpack_dep_test",
  "version": "1.0.0",
  "devDependencies": {
    
    
    "@babel/core": "^7.8.7",
    "@babel/preset-env": "^7.8.7",
    "babel-loader": "^8.0.6",
    "core-js": "^3.6.4",
    "css-loader": "^3.4.2",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.1.0",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-import": "^2.20.1",
    "file-loader": "^5.1.0",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "postcss-preset-env": "^6.7.0",
    "style-loader": "^1.1.3",
    "url-loader": "^3.0.0",
    "webpack": "^4.42.0",
    "webpack-cli": "^3.3.11"
  },
  "browserslist": {
    
    
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
  "eslintConfig": {
    
    
    "extends": "airbnb-base",
    "env": {
    
    
      "browser": true
    }
  }
}

webpack.config.js

const {
    
     resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
process.env.NODE_ENV = 'development';
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
    
    
  entry:"./src/js/entry.js",
    output:{
    
    
        path:resolve(__dirname,'build'),
        filename:'js/built.js'
    },
    module:{
    
    
        rules:[
            {
    
    
                test:/\.less$/,
                use:[MiniCssExtractPlugin.loader,'css-loader',{
    
    
                    // 还需要在package.json中定义browserslist
                    loader: 'postcss-loader',
                    options: {
    
    
                        ident: 'postcss',
                        plugins: () => [require('postcss-preset-env')()]
                    }
                },'less-loader']
            },
            {
    
    
                test:/\.css$/,
                use:[MiniCssExtractPlugin.loader,'css-loader',{
    
    
                    loader: 'postcss-loader',
                    options: {
    
    
                        ident: 'postcss',
                        plugins: () => [require('postcss-preset-env')()]
                    }
                }]
            },
            {
    
    
                // 检查工具:eslint-loader、eslint
                // 检查目标:除node_module下的所有js文件。
                // 检查规则:在package.json中eslintConfig --> airbnb
                test: /\.js$/,
                exclude: /node_modules/,
                enforce: 'pre',// 和babel-loader都处理js文件,而eslint关注的是src而不是build,优先执行
                loader: 'eslint-loader',
                options: {
    
    
                    fix: true
                }
            },
            {
    
    
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                options: {
    
    
                    presets: [
                        [
                            '@babel/preset-env',
                            {
    
    
                                useBuiltIns: 'usage',// 按需加载
                                corejs: {
    
    
                                    version: 3// 指定core-js版本
                                },
                                targets: {
    
    // 指定兼容性做到哪个版本浏览器
                                    chrome: '60',
                                    firefox: '60',
                                    ie: '9',
                                    safari: '10',
                                    edge: '17'
                                }
                            }
                        ]
                    ]
                }
            },
            {
    
    
                test: /\.(jpg|png|gif)$/,
                loader: 'url-loader',
                options: {
    
    
                    limit: 8 * 1024,
                    name: '[hash:10].[ext]',
                    esModule:false,
                    outputPath: 'images'
                }
            },
            {
    
    
                test: /\.html$/,
                loader: 'html-loader'
            },
            {
    
    
                exclude: /\.(html|js|css|less|jpg|png|gif)/,
                loader: 'file-loader',
                options: {
    
    
                    name: '[hash:10].[ext]',
                    outputPath: 'media'
                }
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
    
    
            template: './src/index.html',
            // 压缩html代码
            minify: {
    
    
                collapseWhitespace: true,// 移除空格
                removeComments: true// 移除注释
            }
        }),
        new MiniCssExtractPlugin({
    
    
            filename: 'css/built.css'
        }),
        new OptimizeCssAssetsWebpackPlugin()
    ],
    // 生产环境下会自动压缩js代码
    mode: 'production'
};

实践准备

创建项目:webpack_dep_test
初始化
npm init
npm i webpack webpack-cli -D
// 上篇博客编译打包功能涉及到的所有依赖
npm i css-loader file-loader html-loader html-webpack-plugin less less-loader style-loader url-loader -D
  • src/js/entry.js:空文件
  • webpack.config.js:复制上篇博客产生的webpack.config.js文件
const {
    
     resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    
    
  entry:"./src/js/entry.js",
    output:{
    
    
        path:resolve(__dirname,'build'),
        filename:'js/built.js'
    },
    module:{
    
    
        rules:[
            {
    
    
                test:/\.less$/,
                use:['style-loader','css-loader','less-loader']
            },
            {
    
    
                test:/\.css$/,
                use:['style-loader','css-loader']
            },
            {
    
    
                test: /\.(jpg|png|gif)$/,
                loader: 'url-loader',
                options: {
    
    
                    limit: 8 * 1024,
                    name: '[hash:10].[ext]',
                    esModule:false,
                    outputPath: 'images'
                }
            },
            {
    
    
                test: /\.html$/,
                loader: 'html-loader'
            },
            {
    
    
                exclude: /\.(html|js|css|less|jpg|png|gif)/,
                loader: 'file-loader',
                options: {
    
    
                    name: '[hash:10].[ext]',
                    outputPath: 'media'
                }
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
    
    
            template:'./src/index.html'
        })
    ],
    mode:'development'
};

实践过程

一:css提取

1.优化目标
  • 将所有样式文件从built.js提取出来得到一个bundle,以减小built.js的体积。
  • build/index.html中head标签内link外部的css bundle,而body标签内script外部built.js。
2.操作示例
  • 打包前
    在这里插入图片描述
  • plugin:mini-css-extract-plugin插件的下载、引入、配置
npm i mini-css-extract-plugin -D
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
...
  plugins:[
       	...,
        new MiniCssExtractPlugin({
    
    
            filename: 'css/built.css'// 提取css后输出文件的位置
        })
        ...
    ]
...
  • loader:MiniCssExtractPlugin.loader的配置
    使用MiniCssExtractPlugin.loader替换style-loader,css生效方式由内嵌式(head下style标签内容)变为外部式(head下link标签引入)
...
  module:{
    
    
        rules:[
            {
    
    
                test:/\.less$/,
                use:[MiniCssExtractPlugin.loader,'css-loader','less-loader']
            },
            {
    
    
                test:/\.css$/,
                use:[MiniCssExtractPlugin.loader,'css-loader']
            },
            ...
       ]
	}
...
  • 打包后
    entry.js中引入的所有css、less文件都被打包进built.css文件之中。
    在这里插入图片描述

二:css兼容

1.优化目标
  • 让css兼容更多的浏览器。
2.操作示例
  • 打包前:src/css/test.css
#box1 {
    
    
   width: 100px;
   height: 100px;
   background-color: pink;
   display: flex;
   backface-visibility: hidden;
 }
  • loader:postcss-loader的下载、配置
// postcss-preset-env插件:帮postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式
npm i postcss-loader postcss-preset-env -D
// 设置nodejs的运行环境(让postcss-preset-env插件加载对应环境的配置)
process.env.NODE_ENV = 'development';
...
 module:{
    
    
        rules:[
            {
    
    
                test:/\.less$/,
                use:[MiniCssExtractPlugin.loader,'css-loader',{
    
    
                    // 在css-loader加载之前使用postcss加载
                    // 还需要在package.json中定义browserslist
                    loader: 'postcss-loader',
                    options: {
    
    
                        ident: 'postcss',
                        plugins: () => [require('postcss-preset-env')()]
                    }
                },'less-loader']
            },
            {
    
    
                test:/\.css$/,
                use:[MiniCssExtractPlugin.loader,'css-loader',{
    
    
                    loader: 'postcss-loader',
                    options: {
    
    
                        ident: 'postcss',
                        plugins: () => [require('postcss-preset-env')()]
                    }
                }]
            },
            ...
       ]
  }
  • package.json:配置browserslist(不同环境时需要兼容的浏览器列表)
{
    
    
...,
	"browserslist": {
    
    
	   "development": [
	     "last 1 chrome version",
	     "last 1 firefox version",
	     "last 1 safari version"
	   ],
	   "production": [
	     ">0.2%",
	     "not dead",
	     "not op_mini all"
	   ]
	 }
}
  • 打包后:build/css/built.css(entry.js只引入了test.css一个css文件)
#box1 {
    
    
    width: 100px;
    height: 100px;
    background-color: pink;
    display: flex;
    -webkit-backface-visibility: hidden;
            backface-visibility: hidden;
}

三:css压缩

1.优化目标
  • 压缩以减小css文件体积,加快下载速度。
2.操作示例
  • 打包压缩前:test.css
#box1 {
    
    
    width: 100px;
    height: 100px;
    background-color: pink;
    display: flex;
    backface-visibility: hidden;
}
  • plugin:optimize-css-assets-webpack-plugin的下载、引入、配置
npm i optimize-css-assets-webpack-plugin -D
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
...
 plugins:[
        ...,
        new OptimizeCssAssetsWebpackPlugin()
    ]
...
  • 打包压缩后:build/css/built.css(entry.js只引入了test.css一个css文件)
#box1{
    
    width:100px;height:100px;background-color:pink;display:flex;-webkit-backface-visibility:hidden;backface-visibility:hidden}

四:js检查(语法)

1.优化目标
  • 打包的同时,风格化代码。
2.操作示例
  • 打包前:src/js/test.js(被entry.js引入)与src/js/test2.js(不被entry.js引入)
// 被entry.js引入的test.js
function test(a,b) {
    
    
    a+= 1;
    return a+b
}
console.log(test(3,5))
// 与test.js文件内容一致但未被entry.js引入的test2.js
function test(a,b) {
    
    
    a+= 1;
    return a+b
}
console.log(test(3,5))
  • loader:eslint-loder的下载、配置
// 检查工具:eslint及其loader
npm i eslint-loader eslint -D
// 检查规则:airbnb风格,eslint-config-airbnb-base eslint-plugin-import
npm i eslint-config-airbnb-base eslint-plugin-import -D
module:{
    
    
	rules:[
		...,
		{
    
    
				// 检查工具:eslint-loader、eslint
               // 检查目标:除node_module下的所有js文件。
               // 检查规则:在package.json中eslintConfig --> airbnb
               test: /\.js$/,
               exclude: /node_modules/,
               enforce: 'pre',// 和babel-loader都处理js文件,而eslint关注的是src而不是build,优先执行
               loader: 'eslint-loader',
               options: {
    
    
                   fix: true //自动修复
               }
           },
          ...
	]
}
  • package.json
{
    
    
...,
	"eslintConfig": {
    
    
  		"extends": "airbnb-base",
  		"env": {
    
    
    	"browser": true
 	}
}
  • 打包信息
    在这里插入图片描述
  • 打包后:src/js/test.js(被entry.js引入)与src/js/test2.js(不被entry.js引入)
    test.js被检查并自动修正,而test2.js没有。说明未被entry.js引入的js文件不会被eslint-loader加载,也就不会被eslint检查并自动修正。
// 被entry.js引入的test.js
function test(a, b) {
    
    
  a += 1;
  return a + b;
}
console.log(test(3, 5));
// 与test.js文件内容一致但未被entry.js引入的test2.js
function test(a,b) {
    
    
    a+= 1;
    return a+b
}
console.log(test(3,5))

五:js兼容

注意:生产环境才需要做兼容。

1.优化目标
  • 做好js的代码兼容操作以兼容生产环境下多样的浏览器。
2.操作示例
  • 打包前:src/js/test.js
// 箭头函数等基本语法可以被@babel/preset-env兼容,而Promise等高级语法不可以。
// Promise使用core-js库做兼容处理
let test = (a, b) =>{
    
    
  a += 1;
  return a + b;
};
let promise = new Promise(()=>{
    
    
  setTimeout(()=>{
    
    
    console.log(5)
  },1000)
});
console.log(test(3, 5));
  • loader:babel-loader的下载与配置
    • 依赖核心库 -D:@babel/core
    • 【选用】基本语法兼容库 -D:@babel/preset-env
    • 【选用】部分js语法兼容库 -D(优点:按需加载):core-js
    • 【弃用】全部js语法兼容库 -D(缺点:造成打包体积太大):@babel/ployfill
npm i babel-loader @babel/core @babel/preset-env core-js -D
module:{
    
    
	rules:[
	...,
	{
    
    
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                options: {
    
    
                    presets: [
                        [
                            '@babel/preset-env',
                            {
    
    
                                useBuiltIns: 'usage',// 按需加载
                                corejs: {
    
    
                                    version: 3// 指定core-js版本
                                },
                                targets: {
    
    // 指定兼容性做到哪个版本浏览器
                                    chrome: '60',
                                    firefox: '60',
                                    ie: '9',
                                    safari: '10',
                                    edge: '17'
                                }
                            }
                        ]
                    ]
                }
            },
	...
	]
}
  • 打包后:build/js/built.js
(function(module, __webpack_exports__, __webpack_require__) {
    
    
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_object_to_string__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.object.to-string */ \"./node_modules/core-js/modules/es.object.to-string.js\");\n/* harmony import */ var core_js_modules_es_object_to_string__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_object_to_string__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_promise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.promise */ \"./node_modules/core-js/modules/es.promise.js\");\n/* harmony import */ var core_js_modules_es_promise__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_promise__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_web_timers__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/web.timers */ \"./node_modules/core-js/modules/web.timers.js\");\n/* harmony import */ var core_js_modules_web_timers__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_timers__WEBPACK_IMPORTED_MODULE_2__);\n\n\n\n\nvar test = function test(a, b) {\n  a += 1;\n  return a + b;\n};\n\nvar promise = new Promise(function () {\n  setTimeout(function () {\n    console.log(5);\n  }, 1000);\n});\nconsole.log(test(3, 5));\n\n//# sourceURL=webpack:///./src/js/test.js?");

/***/ })

/******/ });

六:js压缩

1.优化目标
  • 压缩js代码,减小js文件的体积,以加快下载速度。
2.操作示例
  • 未启用压缩前:build/js/built.js
    在这里插入图片描述
  • plugin:webpack内置插件
module.exports = {
    
    
...,
// 生产环境下会自动压缩js代码
  mode: 'production'
}
  • 启用压缩后:build/js/built.js
    在这里插入图片描述

七:html压缩

1.优化目标
  • 压缩html代码,以减小html的体积,加快下载速度。
2.操作示例
  • 打包前:src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webpackDepTest</title>
</head>
<body>
<H1>webpack_dep_test template for src/index.html</H1>
</body>
</html>
  • plugin:html-webpack-plugin的配置(已下载)
   plugins:[
        new HtmlWebpackPlugin({
    
    
            template: './src/index.html',
            // 压缩html代码
            minify: {
    
    
                collapseWhitespace: true,// 移除空格
                removeComments: true// 移除注释
            }
        }),
        ...
   ]
  • 打包后:build/index.html
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>webpackDepTest</title></head><body><h1>webpack_dep_test template for src/index.html</h1><script type="text/javascript" src="js/built.js"></script></body></html>

八:其它静态资源

猜你喜欢

转载自blog.csdn.net/jw2268136570/article/details/104873122