月下三兄貴!Webpack和它的小夥伴vue&&react腳手架基配

簡單來講 Webpack 是一個模塊打包器。它將根據模塊的依賴關係進行靜態分析,而後將這些模塊按照指定的規則生成對應的靜態資源。

webpack讓一切變得再也不復雜

官網:webpack.docschina.org/javascript

webpack是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關係圖(dependency graph),其中包含應用程序須要的每一個模塊,而後將全部這些模塊打包成一個或多個bundlecss

webpack 自己是基於node.js開發的。html

webpack v4.0.0 開始,能夠不用引入一個配置文件(零配置文件),然而webpack仍然仍是高度可配置的。vue

1. 安裝webpack

目前*@vue/clicreate-react-app基本上採用的是webpack 4.0以上版本,因此本次課程以第四代版本爲主;第四代版本須要咱們安裝webpackwebpack-cli*(可執行命令);java

爲了防止全局安裝webpack的版本衝突,咱們真實項目開發的時候基本上以安裝在本地項目中爲主;node

$ npm init -y
 $ npm install webpack webpack-cli --save-dev
OR
$ yarn add webpack webpack-cli -D
複製代碼

2.webpack的基礎使用

  • 初步體驗(零配置)react

    /*
     * 默認會打包SRC目錄中的JS文件(入口默認index.js)
     * 打包完成的目錄默認是DIST/MAIN.JS
     *
     * npx:http://www.ruanyifeng.com/blog/2019/02/npx.html
     * 默認執行node_modules/bin/webpack.cmd文件
     * webpack默認支持CommonJS和ES6 Module的模塊規範,依此進行依賴打包
     */
    $ npx webpack
    複製代碼
  • 自定義基礎配置jquery

    • webpack.config.js OR webpackfile.js
    let path = require('path');
    module.exports = {
    	//=>打包模式 開發環境development 生產環境production
    	mode: 'production',
    	//=>入口
    	entry: './src/index.js',
    	//=>輸出
    	output: {
    		//=>輸出文件的文件名
    		filename: 'bundle.js',
    		//=>輸出目錄的"絕對路徑"
    		path: path.resolve(__dirname, 'dist')
    	}
    }
    複製代碼
  • 自定義配置文件名webpack

    • $ npx webpack --config webpack.config.development.js
    • 可在package.json中配置可執行的腳本命令(區分開發環境)
    "scripts": {
        "serve": "webpack --config webpack.config.development.js",
        "build": "webpack --config webpack.config.production.js"
    },
    複製代碼

3.webpack-dev-server

webpack.js.org/configurati…git

  • 安裝:$ yarn add webpack-dev-server -D

  • 基礎配置

    /* webpack.config.js */
    //=>配置DEV-SERVER
    devServer: {
        //=>端口
    	port: 3000,
        //=>顯示編譯進度
        progress: true,
        //=>指定訪問資源目錄
        contentBase: './dist',
        //=>自動打開瀏覽器
        open: true
    }
    複製代碼
    /* package.json */
    "scripts": {
        "serve": "webpack-dev-server",
        "build": "webpack"
    }
    複製代碼
    • $ npm run serve
    • $ npx webpack-dev-server
  • 代碼更改後,會自動從新編譯,而後自動刷新頁面

4.html-webpack-plugin

www.webpackjs.com/plugins/htm…

  • 安裝:$ yarn add html-webpack-plugin -D

  • 在webpack.config.js中使用

    let HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
        ...,
        //=>在webpack中使用插件
    	plugins: [
    		new HtmlWebpackPlugin({
    			//=>指定本身的模板
    			template: './src/index.html',
    			//=>輸出的文件名
    			filename: 'index.html',
    			//=>給引入的文件設置HASH戳(清除緩存的),也能夠在output中設置 filename: 'bundle.[hash].js' 來生成不一樣的文件
    			hash: true,
    			//=>控制是否以及以何種方式最小化輸出 
        		//=>https://github.com/kangax/html-minifier
    			minify: {
    				collapseWhitespace: true,
    				removeComments: true,
    				removeAttributeQuotes: true,
    				removeEmptyAttributes: true
    			}
    		})
    	]
    }
    複製代碼

5.webpack中的加載器loader:處理樣式的

  • 安裝:$ yarn add css-loader style-loader less less-loader autoprefixer postcss-loader ... -D

  • 使用

    module.exports = {
        //=>配置模塊加載器LOADER
    	module: {
    		//=>模塊規則:使用加載器(默認從右向左執行,從下向上)
    		rules: [{
    			test: /\.(css|less)$/, //=>基於正則表達式匹配哪些模塊須要處理
    			use: [
    				"style-loader", //=>把CSS插入到HEAD中
    				"css-loader", //=>編譯解析@import/URL()這種語法
                    "postcss-loader", //=>設置前綴
                    {
    					loader: "less-loader",
                        options: {
                            //=>加載器額外的配置
                        }
    				}
    			]
    		}]
    	}
    }
    複製代碼

    postcss.config.js

    module.exports = {
    	plugins: [
    		require('autoprefixer')
    	]
    };
    複製代碼

    package.json

    "browserslist": [
        "> 1%",
        "last 2 versions"
    ]
    複製代碼

6.mini-css-extract-plugin 抽離CSS內容

www.npmjs.com/package/min…

  • 安裝 $ yarn add mini-css-extract-plugin optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin -D
let MiniCssExtractPlugin = require('mini-css-extract-plugin'),
	OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'),
	UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
    //=>設置優化項
	optimization: {
		//=>設置壓縮方式
		minimizer: [
			//=>壓縮CSS(可是必須指定JS的壓縮方式)
			new OptimizeCssAssetsWebpackPlugin(),
			//=>壓縮JS
			new UglifyjsWebpackPlugin({
				cache: true, //=>是否使用緩存
				parallel: true, //=>是不是併發編譯
				sourceMap: true, //=>啓動源碼映射(方便調試)
			})
		]
	},
	plugins: [
		//=>使用插件
		new MiniCssExtractPlugin({
			//=>設置編譯後的文件名字
			filename: 'main.css'
		})
	],
	module: {
		rules: [{
			test: /\.(css|less)$/,
			use: [
				// "style-loader",
				//=>使用插件中的LOADER代替STYLE方式
				MiniCssExtractPlugin.loader,
				"css-loader",
                "postcss-loader",
				"less-loader"
			]
		}]
	}
}
複製代碼

上述JS壓縮對於require/import等還存在問題,須要對於ES6中的一些語法進行處理!

7.基於babel實現ES6的轉換和ESLint語法檢測

babeljs.io/

eslint.org/

  • 安裝 $ yarn add babel-loader @babel/core @babel/preset-env @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-transform-runtime -D
  • 安裝 $ yarn add @babel/runtime @babel/polyfill
  • 安裝 $ yarn add eslint eslint-loader -D
module.exports = {
	...,
	module: {
		rules: [...,{
			test: /\.js$/,
			use: [{
				loader: 'babel-loader',
				options: {
					//=>轉換的語法預設(ES6->ES5)
					presets: [
						"@babel/preset-env"
					],
					//=>基於插件處理ES6/ES7中CLASS的特殊語法
					plugins: [
						["@babel/plugin-proposal-decorators", {
							"legacy": true
						}],
						["@babel/plugin-proposal-class-properties", {
							"loose": true
						}],
						"@babel/plugin-transform-runtime"
					]
				}
			}], //=>, "eslint-loader"
			//=>設置編譯時忽略的文件和指定編譯目錄
			include: path.resolve(__dirname, 'src'),
			exclude: /node_modules/
		}]
	}
}
複製代碼

參考https://eslint.org/demo生成 .eslintrc.json

補充知識:在vscode中開啓ES7中類的裝飾器,項目根目錄中設置 jsconfig.json

{
	"compilerOptions": {
		"experimentalDecorators": true
	}
}
複製代碼
@log
class A{
	a=1;
}
複製代碼

8.暴露全局loader

  • $ yarn add expose-loader -D
  • 前置加載器、後置加載器、普通加載器...
//=>內聯加載器
import jquery from 'expose-loader?$!jquery';
console.log(window.$);

{
   //=>只要引入JQUERY就在全局注入$
   test: require.resolve('jquery'),
   use: ['expose-loader?$']
}
複製代碼
let webpack = require('webpack');
module.exports = {
    plugins: [
		//=>在每一個模塊中都注入$
		new webpack.ProvidePlugin({
			'$': 'jquery'
		})
	],
}

//=>頁面中
console.log($);
複製代碼

9.webpack中圖片的處理和分目錄分發

  • 在JS中建立IMG
  • 在CSS中設置背景圖
  • 在HTML中寫死
  • ...

安裝 $ yarn add file-loader url-loader html-withimg-loader -D

module.exports = {
	...,
	module: {
		//=>模塊規則:使用加載器(默認從右向左執行)
		rules: [..., {
			test: /\.(png|jpg|gif)$/i,
			use: [{
				//=>把指定大小內的圖片BASE64
				loader: 'url-loader',
				options: {
					limit: 200 * 1024,
    				outputPath:'/images'
				}
			}],
			include: path.resolve(__dirname, 'src'),
			exclude: /node_modules/
		}, {
			test: /\.html$/,
			use: ['html-withimg-loader']
		}]
	}
}
複製代碼

10. 最後實現文件分目錄發佈

module.exports = {
	output: {
		//=>配置引用前綴(全部資源前加這個地址)
		publicPath: './'
	},
	plugins: [
		new MiniCssExtractPlugin({
			filename: 'css/main.css'
		})
	],
	module: {
		//=>模塊規則:使用加載器(默認從右向左執行)
		rules: [...,{
			test: /\.(png|jpg|gif)$/i,
			use: [{
				options: {
					outputPath: 'images'
				}
			}]
		}]
	}
}
複製代碼

合體!

/* 較完整的webpack基置 在這個文件中設置咱們自定義的打包規則 1. 全部的規則都寫在module.exports={}中 */
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
let MiniCssExtractPlugin = require('mini-css-extract-plugin'), //把css單獨分離出來
    OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'), //壓縮css
    UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin'); //壓縮js
let webpack = require('webpack');
//導入進來的插件都是一個類 new HtmlWebpackPlugin({});

module.exports = {
    //配置優化規則
    optimization: {
        //設置壓縮方式
        minimizer: [
            //壓縮css (產生問題:JS壓縮不在執行本身默認的壓縮方式了,也走的是這個插件,從而致使沒法壓縮,因此必須設置JS的壓縮方式)
            new OptimizeCssAssetsWebpackPlugin(),
            //壓縮js
            new UglifyjsWebpackPlugin({
                cache: true, //是否使用緩存
                parallel: true, //是不是兵法編譯
                sourceMap: true, //啓動源碼映射(方便調試)
            })
        ]
    },
    //配置環境 開發環境development 生產環境production(默認)
    mode: 'production',
    //入口
    entry: ['@babel/polyfill', './src/index-my.js'],
    //出口
    output: {
        //輸出文件的文件名
        //bundle.min.[hash].js 讓每一次生成的文件名都帶着hash值
        filename: 'bundle.min.js',
        // filename: 'bundle.min.[hash].js',
        //輸出的目錄必須是絕對路徑,__dirname當前目錄
        path: path.resolve(__dirname, 'dist'),
        publicPath: './' //給編譯後引入資源地址前面設置的前綴
    },
    //關於webpack-dev-server的一些配置 執行命令:webpack-dev-server --config xxx.js (特色:服務啓動後,默認是不關閉的,當咱們修改src中的源文件,他會自動進行編譯,而後自動刷新瀏覽器,相似於vscode中的Live Server插件,實時刷新)
    devServer: {
        //建立服務指定的端口號
        port: 3000,
        //顯示打包編譯進度
        progress: true,
        //指定當前服務處理資源的目錄
        contentBase: './dist',
        //編譯完成後,自動打開瀏覽器
        open: true
    },
    //使用插件 (數組)
    plugins: [
        new HtmlWebpackPlugin({
            //不指定模版會按照默認模版建立一個html頁面,固然真實項目中通常都是把本身寫好的html進行編譯
            template: './src/index.html',
            //輸出的文件名
            filename: 'index.html',
            //讓咱們引入js後面加上hash戳(清除緩存),可是真實項目中咱們通常都是每一次編譯生成不一樣的js文件引入
            hash: true,
            //控制壓縮
            minify: {
                collapseWhitespace: true,
                removeComments: true,
                removeAttributeQuotes: true,
                removeEmptyAttributes: true
            }
        }),
        new MiniCssExtractPlugin({
            //指定輸出的文件名
            filename: 'main.min.css'
        }),
        //在每一個模塊中都注入$
        new webpack.ProvidePlugin({
            '$': 'jquery'
        }),
    ],
    //使用加載器loader處理規則
    module: {
        rules: [{
            //基於正則匹配處理哪些文件
            test: /\.(css|less)$/,
            //使用哪個加載器,控制使用的loader(有順序的:從右到左執行)
            use: [
                // "style-loader", //把編譯好的css插入到頁面的head中(內嵌式)
                MiniCssExtractPlugin.loader, //使用插件中的loader代替style方式
                "css-loader", //編譯解析@import/URL()這種語法
                // "postcss-loader",//設置前綴的加載器
                {
                    loader: "postcss-loader",
                    options: {
                        ident: 'postcss',
                        plugins: [
                            require('autoprefixer')
                        ]
                    }
                },
                {
                    loader: "less-loader", //編譯less
                    options: {
                        //加載額外的配置
                    }
                }
            ]
        }, {
            test: /\.js$/,
            //處理編譯JS的loader
            use: [{
                loader: 'babel-loader',
                options: {
                    //轉換的語法預設(ES6->ES5)
                    presets: [
                        "@babel/preset-env"
                    ],
                    //=>基於插件處理ES6/ES7中CLASS的特殊語法
                    plugins: [
                        ["@babel/plugin-proposal-decorators", {
                            "legacy": true //處理裝飾器
                        }],
                        ["@babel/plugin-proposal-class-properties", {
                            "loose": true //處理屬性
                        }],
                        "@babel/plugin-transform-runtime"
                    ]
                }
            }],
            //設置編譯時忽略的文件和指定編譯目錄
            include: path.resolve(__dirname, 'src'), //編譯的
            exclude: /node_modules/ //忽略的·
        }, {
            //圖片處理
            test: /\.(png|jpg|gif|jpeg|ico|webp|bpm)$/i,
            use: [{
                loader: 'url-loader',
                options: {
                    //只要圖片小於200KB,在處理的時候直接base64
                    limit: 2 * 1024,
                    //控制打包後圖片所在的目錄
                    outputPath: 'images'
                }
            }]
        }, {
            //處理HTML文件中導入的img文件
            test: /\.(html|htm|xml)$/i,
            use: ['html-withimg-loader']
        }]
    }
}
複製代碼

修改 Vue-cli3 webpack內部配置

  • vue-cli3的配置,所有放在了vue.config.js這一個文件中,講道理,真的清爽。
  • 建立vue.config.js文件命令來審查或修改全局的 CLI 配置。
module.exports = {
	//=>process.env.NODE_ENV:環境變量中存儲的是開發環境仍是生產環境
	publicPath: process.env.NODE_ENV === 'production' ? 'http://www.zhufengpeixun.cn/' : '/',
	//=>outputDir
	//=>自定義目錄名稱,把生成的JS/CSS/圖片等靜態資源放置到這個目錄中
	assetsDir: 'assets',
	//=>關閉生產環境下的資源映射(生產環境下不在建立xxx.js.map文件)
	productionSourceMap: false,
	//=>設置一些webpack配置項,用這些配置項和默認的配置項合併
	configureWebpack: {
		plugins: []
	},
	//=>直接去修改內置的webpack配置項
	chainWebpack: config => {
		//=>config:原始配置信息對象
		config.module
			.rule('images')
			.use('url-loader')
			.loader('url-loader')
			.tap(options => {
				options.limit = 200 * 1024;
				return options;
			});
	},
	//=>修改webpack-dev-server配置(尤爲是跨域代理)
	devServer: {
		proxy: {
			//請求地址 /user/add
			//代理地址 http://api.zhufengpeixun.cn/user/add
			"/": {
				changeOrigin: true,
				target: "http://api.zhufengpeixun.cn/"
			}
		}
	},
	//=>多餘1核cpu時:啓動並行壓縮
	parallel: require('os').cpus().length > 1
}   
複製代碼

修改 create-react-app webpack內部配置

  • react 不一樣,它是導出全部Webpack配置讓開發者自行更改
  • yarn eject 命令 => 把全部隱藏在node_modules中的webpack配置項都暴露出來(方便本身根據項目需求,二次更改webpack配置)
  • 打開導出的config文件夾就能夠增刪改查了 好比修改less的處理配置
  • $ yarn add less less-loader //安裝

打開config/webpack.config.js

const cssRegex = /\.(css|less)$/;
const cssModuleRegex = /\.module\.(css|less)$/;

{
   test: cssRegex,
   exclude: cssModuleRegex,
   use: getStyleLoaders({
     importLoaders: 1,
     sourceMap: isEnvProduction && shouldUseSourceMap,
   }, "less-loader"),
   // Don't consider CSS imports dead code even if the // containing package claims to have no side effects. // Remove this when webpack adds a warning or an error for this. // See https://github.com/webpack/webpack/issues/6571 sideEffects: true, }, // Adds support for CSS Modules (https://github.com/css-modules/css-modules) // using the extension .module.css { test: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, sourceMap: isEnvProduction && shouldUseSourceMap, modules: true, getLocalIdent: getCSSModuleLocalIdent, }, "less-loader"), }, 複製代碼

我真是 [HIGH] 到不行啦!
相關文章
相關標籤/搜索