上大學的時候老師講一門語言,上來的第一節課就是配置各類環境,而一般看到那些腦殼都是一種快要炸的狀態🤯。隨着後來對Linux
的學習以後發現,並無那麼頭疼配置的東西(對於命令這麼複雜的東西均可以接受,那麼配置是否是也不顯得那麼枯燥了😂)。css
本章是結合本身項目中的應該以及查看了webpack
官方文檔以後總結的一篇配置。目的也是鍛鍊本身在配置方面的興趣(可能大家不懂噁心配置的那種感受😩,只能慢慢克服)若有錯誤,還請各位大佬指出🙏,小女子在此謝過🤪。html
話很少說,看正文👇前端
webpack可以把咱們項目中引入的一個或者多個css或者JS資源文件,最終安裝指定的依賴可以打包壓縮成一個css或者一個JS,以此來實現咱們的性能優化。以這種自動化的方法來完成項目的部署和構建,告別了手工。webpack是基於node.js開發的vue
webpack中文網地址node
JavaScript
自己是弱化命名空間概念的,只有全局做用域和函數的私有做用域(ES6
中新增塊做用域),而模塊化開發,從某種意義上來講,是強化了命名空間的概念!react
let xxxModule=(function(){
function fn(){ //... } return { init(){ //... } } })(); xxxModule.init(); 複製代碼
若是須要使用外面的模塊,須要先引入該模塊,可是這種方式在如今的項目中已經不經常使用jquery
文件目錄:webpack
|- lib
|- moduleA.js
|- moduleB.js
|- main.js
git
//main.js
//全局配置 require.config({ baseUrl: 'js/lib', }); require(['moduleB', 'moduleA'], function (moduleB, moduleA) { console.log(moduleB.average(10, 20, 30, 40, 50)); }); 複製代碼
//moduleA.js
define(function () { return { sum(...args) { return args.reduce((total, item) => { return total + item; }); } }; }); 複製代碼
define(['moduleA'], function (moudleA) {
return { average(...args) { args.sort((a, b) => a - b); args.pop(); args.shift(); return moudleA.sum(...args) / args.length; } }; }); 複製代碼
define(function(require, exports, module) {
// 經過 require 引入依賴 let $ = require('jquery'); let spinning = require('./spinning'); // 經過 module.exports 提供接口 module.exports = { init(){} }; }); 複製代碼
module.exports
require
//CommonJS規範的使用
let A = require('./A'); // 第一次REQUIRE A模塊,會把A模塊中的代碼執行, //建立的變量A就是把模塊中module.exports導出的結果拷貝一份給變量 A.sum(x, y); A = require('./A'); // 第二次REQUIRE A模塊,內部默認會看一下以前有沒有導入過,若是導入過不會再把A代碼從新執行,而是直接獲取上一次拷貝的信息 複製代碼
//ES6模塊導入導出的使用
/* * ES6Module是JS新增的模塊導入導出規範(不一樣於AMD 和 CMD【CommonJS】,它是靜態編譯的) * 動態編譯:代碼執行到具體位置的時候纔會進行模塊的導入導出 * (在第十行導入那麼就在第十行才進行導入) * 靜態編譯:代碼尚未執行,就按照依賴的關係吧模塊導入導出和編譯好了 * 模塊的導入都要放在執行的最前面 * 瀏覽器不能直接識別,須要先進行編譯才能夠(webpack能夠完成這個編譯) */ //導出 export function sum(x, y) { return x + y; } export let n = 10; //導入 2種方式 import {sum,n} form './A.js'; import * as A form './A.js' 複製代碼
目前@vue/cli和create-react-app基本上採用的是webpack 4.0以上版本,因此以第四代版本爲主;第四代版本須要咱們安裝webpack和webpack-cli(可執行命令)github
// 爲防止全局安裝webpack致使版本衝突,項目中以本地安裝爲主
$ npm init -y //生成package.json文件 $ npm install webpack webpack-cli --save-dev //安裝開發依賴 // OR $ yarn add webpack webpack-cli -D //若是安裝過yarn的能夠時候這個,速度會快一些 複製代碼
掃盲
運行命令(如下任何一條均可以)
/* * 默認會打包SRC目錄中的JS文件(入口默認index.js) * 打包完成的目錄默認是DIST/MAIN.JS * webpack默認支持CommonJS和ES6 Module的模塊規範,依此進行依賴打包 */ $ npx webpack 複製代碼
若是咱們須要去自定義配置一些文件,首先須要知道這些配置須要寫在哪裏。這裏無論寫在什麼配置文件裏,區別就是執行webpack的命令不同。
webpack.config.js
(這種經常使用)
webpackfile.js
上面兩種是
webpack
默認支持的配置文件名,那麼在執行的時候使用
npx webpack
或者在
package.json
文件中本身配置可執行的命令(上面剛提到的)。
在項目中有時候須要把咱們的配置文件名稱分爲開發配置和生產配置,若是是這個配置文件名那麼在執行webpack
的時候應該使用什麼命令。
好比如今我把本身的配置項寫在webpack.config.dev.js
裏。
第一種方式:那麼須要在上面執行的命令中加入指定的入口npx webpack --config webpack.config.dev.js
。格式就是:npx webpack --config 配置文件名
第二種方式:在package.json
文件裏配置這個命令。好比我想在執行npm run serve
的時候是把只配置的東西執行。就是以下的配置方式:
"scripts": {
"serve": "webpack --config webpack.config.dev.js" }, 複製代碼
以上就是咱們須要在寫本身配置的時候,對於配置文件名的處理。
const path = require('path');
module.exports = { // 設置編譯的模式 development/production(默認) mode: 'production', // 設置編譯的入口文件(項目中通常開發的代碼都要放置到SRC下) entry: './src/main.js', // 設置編譯的出口文件 output: { // 編譯後的文件名 [hash]編譯的時候會隨機在名字中生成惟一的哈希值,以此保證每一次編譯出來的文件是不同的 filename: 'bundle.[hash].min.js', // 輸出的目錄(須要是絕對路徑,使用path完成) path: path.resolve(__dirname, 'build') } }; 複製代碼
咱們把插件的相關配置都放在
plugins
中,是一個數組
$yarn add html-webpack-plugin -D
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { mode: 'production', entry: './src/main.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, // 在WEBPACK中使用插件 plugins: [ // 配置指定的HTML頁面模板(後期在編譯的時候會把編譯好的資源文件自動導入到咱們的頁面模板中) new HtmlWebpackPlugin({ // 模板的路徑 template: './public/index.html', // 編譯後生成的文件名 filename: 'index.html', // 是否把編譯的資源文件導入到頁面中,設置HASH值(清除強緩存,和OUTPUT設置HASH值是同樣的) hash: true, // 把模板中的HTML代碼也進行壓縮編譯(配置規則) // https://github.com/kangax/html-minifier minify: { collapseWhitespace: true, removeComments: true, removeAttributeQuotes: true, removeEmptyAttributes: true } }), ] } 複製代碼
$yarn add clean-webpack-plugin -D
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); //這裏須要把它解構出來,不然不能使用 const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { mode: 'production', entry: './src/main.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, // 在WEBPACK中使用插件 plugins: [ new HtmlWebpackPlugin({ template: './public/index.html', filename: 'index.html', hash: true, minify: { collapseWhitespace: true, removeComments: true, removeAttributeQuotes: true, removeEmptyAttributes: true } }), // 每一次打包都把以前打包的清空 new CleanWebpackPlugin() ] } 複製代碼
能夠幫咱們建立一個web服務(不在用vscode的live server了),服務能夠作如下的事情:
【除非配置項更改了,須要本身從新執行,不然直接都基於它完成自動化處理】
$npx webpack-dev-server
,這樣能夠一直監聽
// 配置DEV-SERVER 編譯後的結果放在計算機內存中,並不會向以前的webpack命令同樣,把編譯後的東西放到build下,dev-server僅僅是在開發模式下,隨時編譯而且預覽的,項目要部署的時候,仍是須要基於webpack編譯打包的
devServer: { // WEB服務的端口號 port: '3000', // 開啓GZIP壓縮 compress: true, // 指定資源訪問的路徑 contentBase: path.resolve(__dirname, "build"), // 自動打開瀏覽器 open: true, // 開啓熱更新 hot: true, // Proxy跨域代理 // proxy: { // '/': 'http://127.0.0.1:8888' // } }, 複製代碼
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 配置多頁面模板 const htmlPlugins = ['index', 'login'].map(item => { return new HtmlWebpackPlugin({ template: `./public/${item}.html`, filename: `${item}.html`, // chunks: ['jquery', item], // 指定當前頁面的依賴項,先引誰就把誰放在前面 chunks: [item], minify: { collapseWhitespace: true, removeComments: true, removeAttributeQuotes: true, removeEmptyAttributes: true } }); }); module.exports = { // 基礎配置 mode: 'production', // entry: './src/main.js', // 多入口 KEY:VALUE entry: { index: './src/main.js', login: './src/login.js', // 若是不想把JQ合併在其它的JS中,想獨立打包出來(多個頁面公共的部分咱們能夠獨立打包出來) // jquery: 'jquery' //內置模塊不須要放在src目錄下 }, output: { // [name]多入口中配置的屬性名 index/login filename: '[name].[hash].min.js', path: path.resolve(__dirname, 'build') }, // 配置DEV-SERVER devServer: { port: '3000', compress: true, open: true, hot: true }, plugins: [ // 配置指定的HTML頁面模板 ...htmlPlugins, // 每一次打包都把以前打包的清空 new CleanWebpackPlugin() ] }; 複製代碼
加載器寫在
module
裏面
$yarn add css-loader style-loader less less-loader autoprefixer postcss-loader -D
css
的前綴以及兼容的
css
是內嵌式的
module.exports = {
// 配置WEBPACK的加載器LOADER module: { // 設置規則和處理方案 默認執行順序:從右到左、從下向上 rules: [{ // 匹配哪些文件基於正則處理(此處是處理CSS/LESS文件) test: /\.(css|less)$/i, use: [ "style-loader", // 把處理好的CSS插入到頁面中(內嵌式) "css-loader", // 處理@import/URL這種語法 "postcss-loader", // 設置CSS前綴(處理兼容 須要搭配autoprefixer一塊兒使用,須要而外再配置一些信息) "less-loader" // 把LESS編譯爲CSS ] }] } }; 複製代碼
postcss.config.js
module.exports = {
plugins: [ require('autoprefixer') ] }; 複製代碼
package.json
// https://github.com/browserslist/browserslist 學習網站
/* * "> 1%" 兼容99%的瀏覽器 * "last 2 versions" 兼容最近的兩個版本 */ "browserslist": [ "> 1%", "last 2 versions" ] 複製代碼
它是一個插件,使用插件先下載
$ yarn add mini-css-extract-plugin –D
這種執行完css是經過link標籤引入到頁面的
const MiniCssExtractPlugin=require('mini-css-extract-plugin');
module.exports = { plugins: [ //=>使用插件 new MiniCssExtractPlugin({ //=>設置編譯後的文件名字 filename: 'main.[hash].css' }) ], module: { rules: [{ test: /\.(css|less)$/, use: [ // "style-loader", //=>使用插件中的LOADER代替STYLE方式 MiniCssExtractPlugin.loader, "css-loader", "postcss-loader", "less-loader" ] }] } } 複製代碼
$yarn add optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin terser-webpack-plugin -D
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetsWebpackPlugin= require('optimize-css-assets-webpack-plugin'); module.exports = { //=>設置優化項 optimization: { //=>設置壓縮方式 minimizer: [ //=>壓縮CSS(可是必須指定JS的壓縮方式) new OptimizeCssAssetsWebpackPlugin(), //=>壓縮JS new TerserPlugin() ] } }; 複製代碼
$yarn add file-loader url-loader html-withimg-loader -D
module.exports = {
module: { //=>模塊規則:使用加載器(默認從右向左執行) rules: [{ // 圖片的處理 file-loader就是編譯圖片的加載器 test: /\.(png|jpe?g|gif|ico|bmp|svg|eot|ttf|woff|woff2)$/i, use: [{ // url-loader在編譯的時候,會把符合條件的圖片進行BASE64,對於不符合條件的仍是繼續使用file-loader處理 loader: "url-loader", options: { limit: 100 * 1024, // 在編譯的時候,把圖片都放在統一的IMAGES文件夾下 name: 'images/[name].[hash].[ext]', esModule: false } }], include: path.resolve(__dirname, 'src'), exclude: /node_modules/ }, { // 編譯HTML中的圖片的,把其按照上述圖片的處理機制處理 test: /\.html$/, use: ['html-withimg-loader'] }] } } 複製代碼
$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
@babel/polyfill和其它的webpack加載器和插件不同,其它的是編譯時(編譯代碼的時候處理),而polyfill是運行時,是在代碼運行的時候,把一些ES7等特殊的語法進行兼容處理
@babel/runtime
@babel/polyfill
@babel/plugin-transform-runtime
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/ }] } } 複製代碼
對於我來講的一個好消息吧,前天本身鼓足了勇氣加了本身膜拜的前端大神,雖然,尬聊了兩句(粉絲見到偶像是否是都是這樣🙈),可是也給了本身在前端路上的信心。激動的心情已經沒法有言語訴說😊
最後咱們你們一塊兒加油,期待有一天咱們均可以與膜拜的大神做爲同事😊