path.resolve
// 只要以/開頭,就變為絕對路徑
// ./和直接寫效果相同
var path = require("path") //引入node的path模塊path.resolve('/foo/bar', './baz') // returns '/foo/bar/baz'
path.resolve('/foo/bar', 'baz') // returns '/foo/bar/baz'
path.resolve('/foo/bar', '/baz') // returns '/baz'
path.resolve('/foo/bar', '../baz') // returns '/foo/baz'
path.resolve('home','/foo/bar', '../baz') // returns '/foo/baz'
path.resolve('home','./foo/bar', '../baz') // returns '當前工作目錄/home/foo/baz'
path.resolve('home','foo/bar', '../baz') // returns '當前工作目錄/home/foo/baz'
webpack.config.js
- 該文件若有更新,需要重啟
- css-loader:由于import引入的樣式文件會作用在全局,若想css模塊化,則設置modules為true
- 默認情況下,將不接受在 HTTPS 上運行且證書無效的后端服務器
Tip
請注意,要完全啟用 HMR ,需要 webpack.HotModuleReplacementPlugin。如果使用 --hot 選項啟動 webpack 或 webpack-dev-server,該插件將自動添加,因此你可能不需要將其添加到 webpack.config.js 中。
加了publicPath后打包的文件在哪?如何利用cdn
/** @Author: your name* @Date: 2021-04-18 15:44:29* @LastEditTime: 2021-08-08 17:58:22* @LastEditors: Please set LastEditors* @Description: In User Settings Edit* @FilePath: \newToDoc:\hyy\webpack\webpack.config.js*/
const path = require("path");// 設置熱更新
const webpack = require('webpack')const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin")// 處理vue文件
const VueLoaderPlugin = require('vue-loader/lib/plugin')module.exports = {mode: 'development', // 不設置的話是生產模式,代碼會壓縮成一行devtool: 'eval-source-map',// 配置sourceMap// 定位到源代碼的錯誤行數// https://webpack.docschina.org/configuration/devtool/// source-map會生成map文件,打包后文件的最后一行會顯示對應的.map文件// inline-source-map不會生成map文件,會將映射關系放在base64文件里,精確到行列(性能消耗大)// inline-cheap-source-map精確到行// inline-cheap-module-source-map檢測到第三方模塊里的錯誤// cheap-module-eval-source-map 開發環境:有提示,速度尚可,無map文件// cheap-module-source-map 有提示,速度比加eval慢,會生成.map文件entry: {// npx webpack 后面跟的入口commonjs: path.resolve(__dirname, "./src/js/commonjs.js"),es6: path.resolve(__dirname, "./src/js/es6.js"),// 完整寫法 因此輸出默認也是main.js(在沒有配置文件名時)// 若改成test: 'xxx',則默認輸出test.js// main: "./src/js/es6.js"},output: {// __dirname指的是當前文件所在文件夾的絕對路徑。path: path.resolve(__dirname + "/dist"),// 輸出的文件名默認是main.js// [name]是占位符寫法,對應entry里的keyfilename: "js/[name].js",// 產出的文件根目錄前綴,index.html引入js時會加上這個前綴// publicPath: 'http://testCdn.com'},module: {// 告訴webpack 遇到什么模塊要如何處理rules: [{test: /\.vue$/,use: ["vue-loader"]},{test: /\.(png|jpe?g|gif)$/,use: {loader: 'file-loader',// v5 版本已廢棄: 請考慮向 asset modules 遷移。// 用的loader要安裝// https://webpack.docschina.org/loaders/file-loader/// npm install file-loader --save-dev// 那么import test from './test.jpg' test就是打包后的圖片文件名(含路徑)// 還可以用url-loader:用于將文件轉換為 base64 URI 的 loader,打包后就不再產出圖片文件了// 若圖片很大且使用url-loader → base64字符串很長 → 打包后文件體積很大 → 加載時間長 這時最好用file-loader// 若圖片很小且使用file-loader → 單獨生成圖片文件 → 多發送一次HTTP請求?不會緩存嗎options: {name: '[name].[ext]',// 當打包后的文件名、擴展名和原來的一樣outputPath: 'imgs/'// 若路徑}// 這是對loader的配置}},{test: /\.(png|jpe?g|gif)$/,use: {loader: 'url-loader',options: {name: '[name].[ext]',outputPath: 'imgs/',limit: 20480,// 20kb 超出大小則會選用file-loader// 用一個url-loader就相當于url-loader + file-loader了}},},{test: /\.js$/,use: {loader: 'babel-loader',options: {// presets和plugins選其一// presets: [["@babel/preset-env", {// useBuiltIns: 'usage',// corejs: 3// }]],plugins: [['@babel/plugin-transform-runtime', {absuluteRuntime: false,corejs: 3,helpers: true,regenerator: true,useESMoudles: false,version: '7.0.0-beta.0'}]]}},// 排除node_modules里第三方文件的代碼exclude: path.resolve(__dirname, 'node_modules')},{test: /\.css$/,// loader執行順序:從后往前,從下往上,先css-loader再style-loader// 當css文件間有依賴時,css-loader會加以分析// style-loader會將css-loader處理后的結果,會放到html的<style></style>里// 可能會產生多個style標簽use: ["style-loader", "css-loader"]},{test: /\.scss$/,use: ["style-loader",// "css-loader",// 以下importLoaders語法表示,如果引入的index.scss文件里又引入了其他.scss文件// 也要用postcss-loader、sass-loader處理它們// 在最新版本的webpack默認有此功能了// 由于import引入的樣式文件會作用在全局,若想css模塊化,則設置modules為true// 配置后使用:import myStyles from 'XXX'// xxx.className =`${myStyles.logo}`{loader: "css-loader",options: {importLoaders: 2,// ?modules: true,}},"postcss-loader","sass-loader"]// 順序不可改動// 翻譯后的樣式代碼就不再有嵌套等瀏覽器不能識別的語法// sass-loader 需要預先安裝 Dart Sass 或 Node Sass// 我們推薦使用 Dart Sass。// npm install --save-dev postcss-loader 處理css3?// autoprefixer自動加上廠商前綴(考慮兼容問題) npm install autoprefixer -D// autoprefixer需和postcss配合使用,創建postcss.config.js配置文件},// 處理字體圖標:讓字體圖標生效{test: /\.(eot|svg|ttf|woff)/,use: ['file-loader']},{test: /\.tpl$/,loader: 'ejs-loader'},]},plugins: [// 打包后自動在dist文件夾下生成index.html// 和module同級// 用到的loader、plugin都需要npm安裝// 實例化// 會以template提供的模板為基礎生成index.html,并會引入output中指定的js文件new HtmlWebpackPlugin({filename: 'index.html',template: path.resolve(__dirname, "./src/index.html"),chunks: ['commonjs', 'es6'],excludeChunks: ['node_modules']}),// 打包前清空dist目錄new CleanWebpackPlugin(),new webpack.HotModuleReplacementPlugin(),new VueLoaderPlugin()],// devServer只存在于開發環境!!線上沒有代理// https://webpack.docschina.org/configuration/dev-server/#root// 使用前先安裝// 充當服務器的作用,啟動本地端口,訪問端口時會返回打包的html的內容devServer: {// 自動打開open: true,host: "localhost",port: 3333,// 接口地址是/Yixiantong開頭的,則轉發到xxxproxy: {'/api': {target: 'http://study.jsplusplus.com',secure: false, // 如果target是https的pathRewrite: {'^/api': ''},// 接口對源有限制changeOrigin: true}},// 開啟熱更新 1. 引入webpack 2. 配置plugins 3. hot設為truehot: true,}
};
postcss.config.js
- 引入autoprefixer
// 參考https://webpack.docschina.org/loaders/postcss-loader/
module.exports = {plugins: [require('autoprefixer')],
};
package.json
- 想在瀏覽器中看到postcss-loader + autoprefixer的效果(使用transform時,翻譯后自動加上廠商前綴:
-webkit-transform: rotate(-45deg)
) - 配置項目針對的是市場份額大于1%,上兩個版本的瀏覽器
"browserslist":["> 1%", "last 2 versions"]
- dev:啟動dev server服務器
- build:相當于npx webpack
- dev server:只要修改了源代碼就能看到最新的結果
- watch: 監聽代碼變化,那就不是運行在port了,而是要運行dist里的index.html
"scripts": {"test": "echo \"Error: no test specified\" && exit 1","dev": "webpack-dev-server --config webpack.config.js","watch": "webpack --watch","build": "webpack --config webpack.config.js"},
clean-webpack-plugin插件
https://www.npmjs.com/package/clean-webpack-plugin
- cnpm install --save-dev clean-webpack-plugin
- 每次打包都能清空dist目錄
請求轉發
- webpack-dev-server底層使用了
http-proxy-middleware
來實現功能
https://webpack.docschina.org/configuration/dev-server/#root
不帶前綴
- 將
http://localhost:3333/Yixiantong/getHomeDatas
轉發到接口的域名下
import axios from 'axios'
// 正式/開發環境的接口地址不同,因此使用相對路徑,而不能寫死
axios.get('/Yixiantong/getHomeDatas').then((res) => {console.log(res)
})
- webpack.config.js
devServer: {// 自動打開open: true,host: "localhost",port: 3333,// 接口地址是/Yixiantong開頭的,則轉發到xxxproxy: {'/Yixiantong': {target: 'http://study.jsplusplus.com',// 接口對源有限制changeOrigin: true}},
}
帶前綴
axios.get('/api/Yixiantong/getHomeDatas').then((res) => {console.log(res)
})
- webpack.config.js
devServer: {// 自動打開open: true,host: "localhost",port: 3333,// 接口地址是/Yixiantong開頭的,則轉發到xxxproxy: {'/api': {target: 'http://study.jsplusplus.com',secure: false, // 如果target是https的pathRewrite: {'^/api': ''},// 接口對源有限制changeOrigin: true}},
}
npm run dev
npm run dev
時并沒有生成dist文件夾- webpack devserver會把打包生成的文件放到內存里,提高了打包效率
HMR熱更新(需要實踐驗證各場景)
- 需要兩步:配置文件 + index.js監聽
- 開啟熱更新后,控制臺會顯示
[WDS] Hot Module Replacement enabled.
- 熱更新,源代碼修改,頁面不會刷新,瀏覽器也不會重新下載html文件,能保留原先渲染的內容、路由、表單輸入、變量等
- style-loader內置了
if(module.hot)
幫助實現了熱更新,不用手動去配置
// 1.
const webpack = require('webpack')
// 2.
plugins: [new webpack.HotModuleReplacementPlugin()
],
// 3.
devServer: {hot: true,
}
- js里的熱更新:
- vue-loader、react babel-preset實現了熱更新
- counter.js(入口)
import number from './number'
const count = document.createElement('div')
count.setAttribute('id', 'count')
count.innerText = 1
document.body.appendChild(count)
setInterval(() => {count.innerText = +count.innerText + 1
}, 1000);number()// 4. 監聽number模塊的變化
if (module.hot) {console.log('module', module)// accept接受監聽的范圍module.hot.accept('./number', () => {console.log('【不要清空counter,且重新執行number】')const oldNumber = document.getElementById('number')document.body.removeChild(oldNumber)number()})
}
- number.js
function number() {console.log('【number里重新執行了】')const div = document.createElement('div')div.setAttribute('id', 'number')div.innerText = 100document.body.appendChild(div)
}export default number
babel
https://blog.csdn.net/weixin_43503511/article/details/118628148
- 安裝babel-loader(建立起webpack和babel的橋梁) babel-core
- 配置mudule → rules
- 安裝babel-preset-env(將ES5轉譯成ES6)
- 安裝babel-polyfill(補丁)
- babel-polyfill(轉換新的API以及一些定義在全局對象上的方法)打包體積增加
- core-js + regenerator 支持所有新特性→ babel-polyfill(將二者組合)
- 按需引入后,不需要在業務代碼中import ‘babel-polyfill’(全局引入),需要安裝core-js
- 使用babel-polyfill會污染全局,它在全局上添加新特性屬性
babel-plugin-transform-runtime
,大致意思是重命名新特性,若用戶也在全局上定義window.Promise則不會沖突 +cnpm i -S @babel/runtime-corejs3
,在開發庫的時候才會用到- 可以將options的內容放入babelrc文件,更加清晰
- preset的執行順序也是從下往上的
Babel 默認只轉換新的 JavaScript 句法(syntax),而不轉換新的
API,比如Iterator、Generator、Set、Map、Proxy、Reflect、Symbol、Promise等全局對象,以及一些定義在全局對象上的方法(比如Object.assign、Array.from等)都不會轉碼。
{test: /\.js$/,use: {loader: "babel-loader",// 這里和babelrc是一樣的options: {presets: [["@babel/preset-env",{useBuiltIns: 'usage',corejs: 3}]]// 告訴polyfill只處理使用到的新特性(按需使用)}},// 排除node_modules里第三方文件的代碼exclude: path.resolve(__dirname, 'node_modules')
},
解析react jsx
- 安裝@babel/preset-react
https://babeljs.io/docs/en/babel-preset-react#docsNav
解析vue
- 安裝vue-loader vue-template-compiler
- 引入VueLoaderPlugin
const VueLoaderPlugin = require('vue-loader/lib/plugin')
rules: [{test: /\.vue$/,use: ["vue-loader"]}
]
plugins: [new VueLoaderPlugin()
],