第12天課程-多頁:多入口,匹配多個打包的jscss
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { mode: 'development', entry: { home: './src/home.js', other: './src/other.js' }, output: { filename: '[name].js', path: path.resolve(__dirname, 'dist') }, plugins: [ new HtmlWebpackPlugin({ template: './src/home.html', filename: 'home.html', chunks:['home'] }), new HtmlWebpackPlugin({ template: './src/other.html', filename: 'other.html', chunks:['other'] }) ] }
補充章節:webpack-modehtml
mode分爲development/production,默認爲production。每一個選項的默認配置以下(common指兩個配置項都存在的屬性):前端
common:vue
//parent chunk中解決了的chunk會被刪除 optimization.removeAvailableModules:true //刪除空的chunks optimization.removeEmptyChunks:true //合併重複的chunk optimization.mergeDuplicateChunks:true
production node
//性能相關配置 performance:{hints:"error"....} //某些chunk的子chunk已一種方式被肯定和標記,這些子chunks在加載更大的塊時沒必要加載 optimization.flagIncludedChunks:true //給常常使用的ids更短的值 optimization.occurrenceOrder:true //肯定每一個模塊下被使用的導出 optimization.usedExports:true //識別package.json or rules sideEffects 標誌 optimization.sideEffects:true //嘗試查找模塊圖中能夠安全鏈接到單個模塊中的段。- - optimization.concatenateModules:true //使用uglify-js壓縮代碼 optimization.minimize:true
developmentreact
//調試 devtool:eval //緩存模塊, 避免在未更改時重建它們。 cache:true //緩存已解決的依賴項, 避免從新解析它們。 module.unsafeCache:true //在 bundle 中引入「所包含模塊信息」的相關注釋 output.pathinfo:true //在可能的狀況下肯定每一個模塊的導出,被用於其餘優化或代碼生成。 optimization.providedExports:true //找到chunk中共享的模塊,取出來生成單獨的chunk optimization.splitChunks:true //爲 webpack 運行時代碼建立單獨的chunk optimization.runtimeChunk:true //編譯錯誤時不寫入到輸出 optimization.noEmitOnErrors:true //給模塊有意義的名稱代替ids optimization.namedModules:true //給模chunk有意義的名稱代替ids optimization.namedChunks:true
webpack運行時還會根據mode設置一個全局變量process.env.NODE_ENV,jquery
這裏的process.env.NODE_ENV不是node中的環境變量,而是webpack.DefinePlugin中定義的全局變量,容許你根據不一樣的環境執行不一樣的代碼.webpack
生產環境下,uglify打包代碼時會自動刪除不可達代碼,也就是說生產環境壓縮後最終的代碼爲:es6
第13天課程-配置source-mapweb
安裝依賴
npm install -D babel-loader @babel/core @babel/preset-env
npm install webpack-dev-server --save-dev
devtool設置項理解,eval 能夠理解爲發射,不是編譯階段產生
//devtool: 'source-map',//產生文件,能夠顯示行和列 //devtool: 'eval-source-map',//不實際產生文件,可是能夠顯示行和列 //devtool: 'cheap-module-source-map',//不顯示列,產生文件 devtool: 'cheap-module-eval-source-map',//不顯示列,不產生文件
試驗代碼src/home.js:
class Demo{ constructor(){ console.loga(); } } let d=new Demo();
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { mode: 'production', entry: { home: './src/home.js', }, output: { filename: 'index.js', path: path.resolve(__dirname, 'dist') }, //devtool: 'source-map',//產生文件,能夠顯示行和列 //devtool: 'eval-source-map',//不實際產生文件,可是能夠顯示行和列 //devtool: 'cheap-module-source-map',//不顯示列,產生文件 devtool: 'cheap-module-eval-source-map',//不顯示列,不產生文件 module: { rules: [ { test: /\.m?js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/home.html', filename: 'index.html', chunks: ['home'] }) ] }
14章節:watch用法,執行npm run build時候開始
更改完代碼以後,當即build,產生編譯文件,
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { mode: 'production', entry: { home: './src/home.js', }, output: { filename: 'index.js', path: path.resolve(__dirname, 'dist') }, watch:true, watchOptions:{ poll:1000,//每秒檢查一次變更 aggregateTimeout:500,//防抖延遲,500秒以後輸入, ignored: /node_modules/ //ignored: "files/**/*.js" }, module: { rules: [ { test: /\.m?js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/home.html', filename: 'index.html', chunks: ['home'] }) ] }
15:webpack小插件介紹
cleanWebpackPlugin:npm install clean-webpack-plugin -D
關鍵代碼:
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 引入清除文件插件 new CleanWebpackPlugin()
官方說明:詳細說明
/** * All files inside webpack's output.path directory will be removed once, but the * directory itself will not be. If using webpack 4+'s default configuration, * everything under <PROJECT_DIR>/dist/ will be removed. * Use cleanOnceBeforeBuildPatterns to override this behavior. * * During rebuilds, all webpack assets that are not used anymore * will be removed automatically. * * See `Options and Defaults` for information */
全部output.path目錄都會被一次刪除,目錄自己不會刪除
copyWebPackPlugin:
const CopyWebpackPlugin = require('copy-webpack-plugin'); // 文件拷貝 new CopyWebpackPlugin([{from:'./doc',to:'./'}])
bannerPlugin:
let webpack=require('webpack'); new webpack.BannerPlugin('版權全部,違反必究 2019 copyright')
本章節webpack配置文件
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 引入清除文件插件 const CopyWebpackPlugin = require('copy-webpack-plugin'); // 引入清除文件插件 let webpack=require('webpack'); module.exports = { mode: 'development', entry: { home: './src/home.js', }, output: { filename: 'index.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.m?js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/home.html', filename: 'index.html', chunks: ['home'] }), new CleanWebpackPlugin(), new CopyWebpackPlugin([{from:'./doc',to:'./'}]), new webpack.BannerPlugin('版權全部,違反必究 2019 copyright') ] }
16章節:webpack跨域問題
webpack端口默認是8080 若是請求這麼寫,會跨域,跨域是瀏覽器自己的限制,若是使用瀏覽器跨域設置,能夠請求到數據
1:devServer-proxy設置
本地express服務器:localhost:3000/api/user 代理設置:proxy:{'/api':'http://localhost:3000'}
可是不是服務端每一個接口都是api開頭的,因此須要用下面的方式 本地express服務器:localhost:3000/user 代理devServer設置
2:單純模擬數據mock 啓動鉤子函數
3:有服務端,可是不想用代理處理,用express 啓動webpack 端口用express端口
npm install webpack-dev-middleware --save-dev //安裝依賴
server.js let express = require('express'); let config=require('./webpack.config'); const webpack = require('webpack'); const middleware = require('webpack-dev-middleware'); const compiler = webpack(config); let app = express(); app.use( middleware(compiler, { }) ); app.get('/api/user', (req, res) => { res.json({ "name": "珠峯設計-express" }); }) app.listen(3000);
webpack.config.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 引入清除文件插件 const CopyWebpackPlugin = require('copy-webpack-plugin'); // 引入清除文件插件 let webpack = require('webpack'); module.exports = { mode: 'development', entry: { home: './src/home.js', }, devServer: { contentBase: path.join(__dirname, 'dist'), compress: true, before(app) { console.log(app); app.get('/before', (req, res) => { res.json({ "name": "我試mock數據-before" }); }) }, port: 9000, /*proxy:{ '/api':'http://localhost:3000' } */ proxy: { '/api': { target: 'http://localhost:3000', pathRewrite: { '/api': '' }//須要先啓動3000端口的服務 } } }, output: { filename: 'index.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.m?js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] }, plugins: [ new HtmlWebpackPlugin({ template: './src/home.html', filename: 'index.html', chunks: ['home'] }), new CleanWebpackPlugin(), new CopyWebpackPlugin([{ from: './doc', to: './' }]), new webpack.BannerPlugin('版權全部,違反必究 2019 copyright') ] }
17:resolve屬性的配置,解析的意思,文件查找別名後綴等配置
Webpack 在啓動後會從配置的入口模塊出發找出全部依賴的模塊,Resolve 配置 Webpack 如何尋找模塊所對應的文件。 Webpack 內置 JavaScript 模塊化語法解析功能,默認會採用模塊化標準里約定好的規則去尋找,但你也能夠根據本身的須要修改默認的規則
安裝後模塊:就是會在node_modules裏面Bin裏面有,不須要"/"
模塊目錄指定:
別名:引入bootstrap樣式爲例
alias:名稱比較長,可是文件名稱比較長,想取一個短的名字
mainFields 可是能不能先找style 再找js mainFields:['style','main'] 字段名稱爲bootstrap裏面package.json key
須要css的話,把css加進去
18:定義環境變量
把環境變量注入代碼裏面,插件:new webpack.
new webpack.DefinePlugin({ 'DEV':"'dev'", 'DevTest':JSON.stringify('devTest'), 'DevBoolean':true, 'DevBooleanWithSingle':'true', 'EXPRESSIONWITHNOTDOT':'1+1', 'EXPRESSIONWITHDOT':JSON.stringify('1+1'), }),
輸出結果:
19;區分不一樣環境變量
webpack.config.js分開生產和開發環境,
webpack.base.js :公共的
webpack.dev.js 開發的
webpack.prod.js 生產的
安裝插件npm install webpack-merge -D
webpack.dev.js文件內容 ,這樣咱們就能夠把配置給分開
const { smart } = require('webpack-merge'); const base = require('./webpack.base.js'); module.exports = smart(base, {'mode':'development'})
20:優化設置
新建一個空的工程並安裝插件
npm init -y npm install webpack webpack-cli html-web pack-plugin @babel/core babel-loader @babel/preset-env @babel/preset-react jquery -D
>webpack配置裏面的noParse:不解析依賴項
src-index.js文件
import jquery from 'jquery';
這樣反覆編譯幾回發現,編譯時間是縮短了,我電腦表現大概節約200ms時間
>IgnorePlugin插件:忽略某些模塊,不打包進來
webpack配置裏面exclude include排除目錄(node_modules),包含src
安裝moment 時間處理庫:npm insall moment -D
安裝開發服務器:npm install webpack-dev-server
webpack.config.js文件
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpack=require('webpack'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, module: { rules: [ { test: /\.m?js$/, exclude: /(node_modules|bower_components)/, include:path.resolve("src"), use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/preset-react'] } } } ] }, plugins: [ new HtmlWebpackPlugin({ template: './public/index.html', }), new webpack.IgnorePlugin(/\.\/locale/,/moment/) ], };
index.js
import jquery from 'jquery'; import moment from 'moment'; import 'moment/locale/zh-cn'; moment.locale('zh-cn');//這一句不引入也正確 let r=moment().endOf('day').fromNow(); console.log(r);
>dllPlugin插件:減小打包體積
安裝npm install react react-dom
>happypack多線程打包js,css打包 中間插入一層happypack
>webpack自帶的一些優化,避免沒必要要的tree-shaking,做用域提高scope hosting
生產環境去除沒有用的代碼,開發環境有的,tree-shaking
只有import 管用,require不能夠,es6模塊會把結果放到default對象上
前端推薦import
webpack會省略一些能夠簡化的代碼
25:webpack抽取公共代碼 optimization-splitChunks-cacheGroups裏面配置,多入口文件
webpack配置文件 optimization:{ splitChunks:{ cacheGroups:{ common:{ chunks:'initial',//抽離階段 minSize:0,抽離大小 minChunks:2//引用多少次就開始抽離 }, vendor:{ priority:1, //避免直接走第一步,不走第二步 test:/node_modules/, chunks:'initial', minSize:0, minChunks;2 } } } }
26:懶加載功能webpack
意義:安裝插件@babel/plugin-syntax-dynamic-import
vue react的路由懶加載實現
button的點擊事件裏面代碼
import('./source.js');
options:{ presets:['@babel/preset-env','@babel/preset-react'], plugins:['@babel/plugin-syntax-dynamic-import '] }
27:webpack熱更新 開發環境用 默認強制更新,從新編譯
devserver:hot:true
兩個插件:webpack.NamedModulesPlugin /webpack.HotModuleReplacementPlugin
index.js
import s from './a.js'; if (module.hot) { module.hot.accept('./a.js', (s) => { let a=import('./a');// a.then(function(response){ console.log(response); }); let b=require('./a.js'); console.log(b); }) }
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpack=require('webpack'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, devServer:{ port:3000, open:true, hot:true, contentBase:'./dist' }, module: { rules: [ { test: /\.m?js$/, exclude: /(node_modules|bower_components)/, include:path.resolve("src"), use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/preset-react'] } } } ] }, plugins: [ new HtmlWebpackPlugin({ template: './public/index.html', }), new webpack.IgnorePlugin(/\.\/locale/,/moment/), new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin() ], };
28-33:webpack-tapable 同步鉤子和異步鉤子
webpack 本質事件流,主要依賴於發佈訂閱模式