最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

配置Webpack?SourceMap?實踐教程

 更新時間:2024年03月14日 11:12:47   作者:我樂了.  
這篇文章主要介紹了如何配置Webpack?SourceMap,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧

Source Map 簡介

Source Map(源代碼地圖)就是解決此類問題最好的辦法,從它的名字就能夠看出它的作用:映射轉(zhuǎn)換后的代碼與源代碼之間的關(guān)系。一段轉(zhuǎn)換后的代碼,通過轉(zhuǎn)換過程中生成的 Source Map 文件就可以逆向解析得到對應(yīng)的源代碼。

目前很多第三方庫在發(fā)布的文件中都會同時提供一個 .map 后綴的 Source Map 文件。例如 jQuery。我們可以打開它的 Source Map 文件看一下,如下圖所示:

這是一個 JSON 格式的文件,為了更容易閱讀,我提前對該文件進行了格式化。這個 JSON 里面記錄的就是轉(zhuǎn)換后和轉(zhuǎn)換前代碼之間的映射關(guān)系,主要存在以下幾個屬性:

  • version 是指定所使用的 Source Map 標準版本;
  • sources 中記錄的是轉(zhuǎn)換前的源文件名稱,因為有可能出現(xiàn)多個文件打包轉(zhuǎn)換為一個文件的情況,所以這里是一個數(shù)組;
  • names 是源代碼中使用的一些成員名稱,我們都知道一般壓縮代碼時會將我們開發(fā)階段編寫的有意義的變量名替換為一些簡短的字符,這個屬性中記錄的就是原始的名稱;
  • mappings 屬性,這個屬性最為關(guān)鍵,它是一個叫作 base64-VLQ 編碼的字符串,里面記錄的信息就是轉(zhuǎn)換后代碼中的字符與轉(zhuǎn)換前代碼中的字符之間的映射關(guān)系,具體如下圖所示:

一般我們會在轉(zhuǎn)換后的代碼中通過添加一行注釋的方式來去引入 Source Map 文件。不過這個特性只是用于開發(fā)調(diào)試的,所以最新版本的 jQuery 已經(jīng)去除了引入 Source Map 的注釋,我們需要手動添加回來,這里我們在最后一行添加 //# sourceMappingURL=jquery-3.4.1.min.map,具體效果如下:

這樣我們在 Chrome 瀏覽器中如果打開了開發(fā)人員工具,它就會自動請求這個文件,然后根據(jù)這個文件的內(nèi)容逆向解析出來源代碼,以便于調(diào)試。同時因為有了映射關(guān)系,所以代碼中如果出現(xiàn)了錯誤,也就能自動定位找到源代碼中的位置了。

我們回到瀏覽器中,打開開發(fā)人員工具,找到 Source 面板,這里我們就能看到轉(zhuǎn)換前的 jQuery 源代碼了,具體效果如下圖所示:

我們還可以添加一個斷點,然后刷新頁面,進行單步調(diào)試,此時調(diào)試過程中使用的就是源代碼而不是壓縮過后的代碼,具體效果如下圖所示:

Webpack 中配置 Source Map

我們使用 Webpack 打包的過程,同樣支持為打包結(jié)果生成對應(yīng)的 Source Map。用法上也很簡單,不過它提供了很多不同模式,導(dǎo)致大部分初學(xué)者操作起來可能會比較懵。那接下來我們就一起研究一下在 Webpack 中如何開啟 Source Map,然后再來了解一下幾種不同的 Source Map 模式之間存在哪些差異。

我們回到配置文件中,這里我們要使用的配置屬性叫作 devtool。這個屬性就是用來配置開發(fā)過程中的輔助工具,也就是與 Source Map 相關(guān)的一些功能。我們可以先將這個屬性設(shè)置為 source-map,具體代碼如下:

// ./webpack.config.js
module.exports = {
  devtool: 'source-map' // source map 設(shè)置
}

然后打開命令行終端,運行 Webpack 打包。打包完成過后,我們打開 dist 目錄,此時這個目錄中就會生成我們 bundle.js 的 Source Map 文件,與此同時 bundle.js 中也會通過注釋引入這個 Source Map 文件,具體如下圖所示:

我們再回到命令行,通過 serve 工具把打包結(jié)果運行起來,然后打開瀏覽器,再打開開發(fā)人員工具,此時我們就可以直接定位到錯誤所在的位置了。當然如果需要調(diào)試,這里也可以直接調(diào)試源代碼。

如果你只是需要使用 Source Map 的話,操作到這里就已經(jīng)實現(xiàn)了。但是只會使用這種最普通的 Source Map 模式還遠遠不夠。

為什么這么說呢?

因為現(xiàn)階段 Webpack 支持的 Source Map 模式有很多種。每種模式下所生成的 Source Map 效果和生成速度都不一樣。顯然,效果好的一般生成速度會比較慢,而生成速度快的一般就沒有什么效果。

那具體哪種 Source Map 模式才是最好呢?這里我們還需要繼續(xù)去探索。

Webpack 中的 devtool 配置,除了可以使用 source-map 這個值,它還支持很多其他的選項,具體的我們可以參考文檔中的不同模式的對比表。

上表分別從初次構(gòu)建速度、監(jiān)視模式重新構(gòu)建速度、是否適合生成環(huán)境使用,以及 Source Map 的質(zhì)量,這四個維度去橫向?qū)Ρ攘瞬煌?Source Map 模式之間的差異。

通過表格中四個維度的對比你可能覺得不夠清晰,也不太好理解,所以接下來我們會根據(jù)表格中的介紹,通過實際操作來體會這些模式之間的差異,從而帶你找到適合自己的最佳實踐。

Eval 模式

首先來看 eval 模式。在去具體了解 Webpack eval 模式的 Source Map 之前,我們需要先了解一下 JavaScript 中 eval 的一些特點。

eval 其實指的是 JavaScript 中的一個函數(shù),可以用來運行字符串中的 JavaScript 代碼。例如下面這段代碼,字符串中的 console.log("foo~") 就會作為一段 JavaScript 代碼被執(zhí)行:

const code = 'console.log("foo~")'
eval(code) // 將 code 中的字符串作為 JS 代碼執(zhí)行

在默認情況下,這段代碼運行在一個臨時的虛擬機環(huán)境中,我們在控制臺中就能夠看到:

其實我們可以通過 sourceURL 來聲明這段代碼所屬文件路徑,接下來我們再來嘗試在執(zhí)行的 JavaScript 字符串中添加一個 sourceURL 的聲明,具體操作如下:

具體就是在 eval 函數(shù)執(zhí)行的字符串代碼中添加一個注釋,注釋的格式:# sourceURL=./path/to/file.js,這樣的話這段代碼就會執(zhí)行在指定路徑下。

在了解了 eval 函數(shù)可以通過 sourceURL 指定代碼所屬文件路徑這個特點過后,我們再來嘗試使用這個叫作 eval 模式的 Source Map。

我們回到 Webpack 的配置文件中,將 devtool 屬性設(shè)置為 eval,具體如下:

// ./webpack.config.js
module.exports = {
  devtool: 'eval'
}

然后我們回到命令行終端再次運行打包,打包過后,找到生成的 bundle.js 文件,你會發(fā)現(xiàn)每個模塊中的代碼都被包裹到了一個 eval 函數(shù)中,而且每段模塊代碼的最后都會通過 sourceURL 的方式聲明這個模塊對應(yīng)的源文件路徑,具體如下:

那此時如果我們回到瀏覽器運行這里的 bundle.js,一旦出現(xiàn)錯誤,瀏覽器的控制臺就可以定位到具體是哪個模塊中的代碼,具體效果如下:

但是當你點擊控制臺中的文件名打開這個文件后,看到的卻是打包后的模塊代碼,而并非我們真正的源代碼,具體如下:

綜上所述,在 eval 模式下,Webpack 會將每個模塊轉(zhuǎn)換后的代碼都放到 eval 函數(shù)中執(zhí)行,并且通過 sourceURL 聲明對應(yīng)的文件路徑,這樣瀏覽器就能知道某一行代碼到底是在源代碼的哪個文件中。

因為在 eval 模式下并不會生成 Source Map 文件,所以它的構(gòu)建速度最快,但是缺點同樣明顯:它只能定位源代碼的文件路徑,無法知道具體的行列信息。

案例準備工作

為了可以更好地對比不同模式的 Source Map 之間的差異,這里我們使用一個新項目,同時創(chuàng)建出不同模式下的打包結(jié)果,通過具體實驗來橫向?qū)Ρ人鼈冎g的差異。

在這個案例中,項目中只有兩個 JS 模塊,在 main.js 中,我故意加入了一個運行時錯誤,具體項目結(jié)構(gòu)和部分代碼如下:

└─ 07-devtool-diff
   ├── src
   │   ├── heading.js
   │   └── main.js
   ├── package.json
   └── webpack.config.js
// ./src/main.js
import createHeading from './heading.js'
const heading = createHeading()
document.body.append(heading)
console.log('main.js running')
// 運行時錯誤
console.log111('main.js running')

然后我們打開 Webpack 的配置文件,在這個文件中定義一個數(shù)組,數(shù)組中每一個成員都是 devtool 配置取值的一種,具體代碼如下:

const allDevtoolModes = [
  'eval',
  'cheap-eval-source-map',
  'cheap-module-eval-source-map',
  'eval-source-map',
  'cheap-source-map',
  'cheap-module-source-map',
  'inline-cheap-source-map',
  'inline-cheap-module-source-map',
  'source-map',
  'inline-source-map',
  'hidden-source-map',
  'nosources-source-map'
]

在上一課時中我們也提到過,Webpack 的配置文件除了可以導(dǎo)出一個配置對象,還可以導(dǎo)出一個數(shù)組,數(shù)組中每一個元素就是一個單獨的打包配置,那這樣就可以在一次打包過程中同時執(zhí)行多個打包任務(wù)。

例如,我們這里導(dǎo)出一個數(shù)組,然后在這個數(shù)組中添加兩個打包配置,它們的 entry 都是 src 中的 main.js,不過它們輸出的文件名不同,具體代碼如下:

// ./webpack.config.js
module.exports = [
  {
    entry: './src/main.js',
    output: {
      filename: 'output1.js'
    }
  },
  {
    entry: './src/main.js',
    output: {
      filename: 'output2.js'
    }
  }
]

這么配置的話,再次打包就會有兩個打包子任務(wù)工作,我們的 dist 中生成的結(jié)果也就是兩個文件,具體結(jié)果如下:

image (13).png

了解了 Webpack 這種配置用法過后,我們再次回到配置文件中,遍歷剛剛定義的數(shù)組,為每一個模式單獨創(chuàng)建一個打包配置,這樣就可以一次性生成所有模式下的不同結(jié)果,這比我們一個一個去試驗的效率更高,而且對比起來也更明顯。

具體配置代碼如下:

// ./webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')
const allModes = [
‘eval',
‘cheap-eval-source-map',
‘cheap-module-eval-source-map',
‘eval-source-map',
‘cheap-source-map',
‘cheap-module-source-map',
‘inline-cheap-source-map',
‘inline-cheap-module-source-map',
‘source-map',
‘inline-source-map',
‘hidden-source-map',
‘nosources-source-map'
]
module.exports = allModes.map(item => ({
devtool: item,
mode: ‘none',
entry: ‘./src/main.js',
output: {
filename: js/<span class="hljs-subst">${item}</span>.js
},
module: {
rules: [
{
test: /.jsKaTeX parse error: Expected 'EOF', got '}' at position 342: … } }? ] }, <…{item}.html`
})
]
}))

這里簡單解釋一下這個配置中的部分配置用意:

  • 定義 devtool 屬性,它就是當前所遍歷的模式名稱;
  • 將 mode 設(shè)置為 none,確保 Webpack 內(nèi)部不做額外處理;
  • 設(shè)置打包入口和輸出文件名稱,打包入口都是 src/main.js,輸出文件名稱我們就放在 js 目錄中,以模式名稱命名,至于為什么放在單獨目錄中,你可以在接下來的內(nèi)容中找到答案;
  • 為 js 文件配置一個 babel-loader,配置 babel-loader 的目的是稍后能夠辨別其中一類模式的差異。
  • 配置一個 html-webpack-plugin,也就是為每個打包任務(wù)生成一個 HTML 文件,通過前面的內(nèi)容,我們知道 html-webpack-plugin 可以生成使用打包結(jié)果的 HTML,接下來我們就是通過這些 HTML 在瀏覽器中進行嘗試。

配置完成以后,我們再次回到命令行終端運行打包,那此時這個打包過程就自動生成了不同模式下的打包結(jié)果,具體結(jié)果如下圖所示:

然后我們通過 serve 把結(jié)果運行起來,打開瀏覽器,此時我們能夠在頁面中看到每一個使用不同模式 Source Map 的 HTML 文件,具體如下圖:

那如果剛剛沒有把 JS 文件輸出到單獨目錄中,這里的文件就會非常多,導(dǎo)致 HTML 文件尋找起來特別麻煩。

不同模式的對比

有了不同模式下生成的結(jié)果過后,我們就可以仔細去對比不同 Source Map 模式之間的具體差異了。其實也沒必要真的一個一個去看,這里我先帶你看幾個比較典型的模式,然后找出它們的規(guī)律,這樣你就再也不用頭大了。

首先 eval 模式,這個模式剛剛已經(jīng)單獨看過了,它就是將模塊代碼放到 eval 函數(shù)中執(zhí)行,并且通過 sourceURL 標注所屬文件路徑,在這種模式下沒有 Source Map 文件,所以只能定位是哪個文件出錯,具體效果如下圖:

然后我們再來看一個叫作 eval-source-map 的模式,這個模式也是使用 eval 函數(shù)執(zhí)行模塊代碼,不過這里有所不同的是,eval-source-map 模式除了定位文件,還可以定位具體的行列信息。相比于 eval 模式,它能夠生成 Source Map 文件,可以反推出源代碼,具體效果如下:

緊接著我們再來看一個叫作 cheap-eval-source-map 的模式。根據(jù)這個模式的名字就能推斷出一些信息,它就是在 eval-source-map 基礎(chǔ)上添加了一個 cheap,也就是便宜的,或者叫廉價的。用計算機行業(yè)的常用說法,就是閹割版的 eval-source-map,因為它雖然也生成了 Source Map 文件,但是這種模式下的 Source Map 只能定位到行,而定位不到列,所以在效果上差了一點點,但是構(gòu)建速度會提升很多,具體效果如下圖:

接下來再看一個叫作 cheap-module-eval-source-map 的模式。慢慢地我們就發(fā)現(xiàn) Webpack 中這些模式的名字不是隨意的,好像都有某種規(guī)律。這里就是在 cheap-eval-source-map 的基礎(chǔ)上多了一個 module,具體效果如下圖:

這種模式同樣也只能定位到行,它的特點相比于 cheap-eval-source-map 并不明顯 ,如果你沒有發(fā)現(xiàn)差異,可以再去看看上一種模式,仔細做一個對比,相信對比之后你會發(fā)現(xiàn),cheap-module-eval-source-map 中定位的源代碼與我們編寫的源代碼是一模一樣的,而 cheap-eval-source-map 模式中定位的源代碼是經(jīng)過 ES6 轉(zhuǎn)換后的結(jié)果,具體對比如下(左圖是 cheap-eval-source-map):

這也是為什么之前我要給 JS 文件配置 Loader 的原因:因為這種名字中帶有 module 的模式,解析出來的源代碼是沒有經(jīng)過 Loader 加工的,而名字中不帶 module 的模式,解析出來的源代碼是經(jīng)過 Loader 加工后的結(jié)果。也就是說如果我們想要還原一模一樣的源代碼,就需要選擇 cheap-module-eval-source-map 模式。

了解了這些過后,你基本上就算通盤了解了 Webpack 中所有 Source Map 模式之間的差異,因為其它的模式無外乎就是這幾個特點的排列組合罷了。

例如,我們再來看一個 cheap-source-map 模式,這個模式的名字中沒有 eval,意味著它沒用 eval 執(zhí)行代碼,而名字中沒有 module,意味著 Source Map 反推出來的是 Loader 處理后的代碼,有 cheap 表示只能定位源代碼的行號。

那以上就是我們在日常開發(fā)過程中經(jīng)常用到的幾種 Source Map 模式,你在嘗試的時候一定要注意:找規(guī)律很重要。

除此之外,還有幾個特殊一點的模式,我們單獨介紹一下:

  • inline-source-map 模式

它跟普通的 source-map 效果相同,只不過這種模式下 Source Map 文件不是以物理文件存在,而是以 data URLs 的方式出現(xiàn)在代碼中。我們前面遇到的 eval-source-map 也是這種 inline 的方式。

  • hidden-source-map 模式

在這個模式下,我們在開發(fā)工具中看不到 Source Map 的效果,但是它也確實生成了 Source Map 文件,這就跟 jQuery 一樣,雖然生成了 Source Map 文件,但是代碼中并沒有引用對應(yīng)的 Source Map 文件,開發(fā)者可以自己選擇使用。

  • nosources-source-map 模式:

在這個模式下,我們能看到錯誤出現(xiàn)的位置(包含行列位置),但是點進去卻看不到源代碼。這是為了保護源代碼在生產(chǎn)環(huán)境中不暴露。

寫在最后

雖然 Webpack 中支持各種各樣的 Source Map 模式,但一般應(yīng)用開發(fā)時我們只會用到其中的幾種。其實在我們掌握了它們的特點過后,選擇上就沒有什么需要糾結(jié)的地方了。

這里再分享一下我個人開發(fā)時的選擇,供你參考。

首先開發(fā)過程中(開發(fā)環(huán)境),我會選擇 cheap-module-eval-source-map,原因有以下三點:

  • 我使用框架的情況會比較多,以 React 和 Vue.js 為例,無論是 JSX 還是 vue 單文件組件,Loader 轉(zhuǎn)換后差別都很大,我需要調(diào)試 Loader 轉(zhuǎn)換前的源代碼。
  • 一般情況下,我編寫的代碼每行不會超過 80 個字符,對我而言能夠定位到行到位置就夠了,而且省略列信息還可以提升構(gòu)建速度。
  • 雖然在這種模式下啟動打包會比較慢,但大多數(shù)時間內(nèi)我使用的 webpack-dev-server 都是在監(jiān)視模式下重新打包,它重新打包的速度非???。

綜上所述,開發(fā)環(huán)境下我會選擇 cheap-module-eval-source-map。

至于發(fā)布前的打包,也就是生產(chǎn)環(huán)境的打包,我選擇 none,它不會生成 Source Map。原因很簡單:

  • 首先,Source Map 會暴露我的源代碼到生產(chǎn)環(huán)境。如果沒有控制 Source Map 文件訪問權(quán)限的話,但凡是有點技術(shù)的人都可以很容易的復(fù)原項目中涉及的絕大多數(shù)源代碼,這非常不合理也不安全,我想很多人可能都忽略了這個問題。
  • 其次,調(diào)試應(yīng)該是開發(fā)階段的事情,你應(yīng)該在開發(fā)階段就盡可能找到所有問題和隱患,而不是到了生產(chǎn)環(huán)境中再去全民公測。如果你對自己的代碼實在沒有信心,我建議你選擇 nosources-source-map 模式,這樣出現(xiàn)錯誤可以定位到源碼位置,也不至于暴露源碼。

當然這些選擇不是絕對的,我們理解這些模式之間的差異的目的,就是為了可以在不同環(huán)境中快速選擇一個合適的模式,而不是尋求一個通用法則,開發(fā)行業(yè)也根本不會有絕對的通用法則!

除此之外,我還要強調(diào)一點,Source Map 并不是 Webpack 特有的功能,它們兩者的關(guān)系只是:Webpack 支持 Source Map。大多數(shù)的構(gòu)建或者編譯工具也都支持 Source Map。希望你不要把它們二者捆綁到一起,混為一談。

到此這篇關(guān)于配置 Webpack SourceMap 實踐教程的文章就介紹到這了,更多相關(guān)Webpack SourceMap配置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JS實現(xiàn)的3des+base64加密解密算法完整示例

    JS實現(xiàn)的3des+base64加密解密算法完整示例

    這篇文章主要介紹了JS實現(xiàn)的3des+base64加密解密算法,結(jié)合完整實例形式分析了JavaScript實現(xiàn)的3des+base64加密解密算法簡單使用技巧,需要的朋友可以參考下
    2018-05-05
  • 淺析JS中的 map, filter, some, every, forEach, for in, for of 用法總結(jié)

    淺析JS中的 map, filter, some, every, forEach, for in, for of 用法總

    本文是小編給大家總結(jié)的關(guān)于javascript中的map, filter, some, every, forEach, for in, for of 用法,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-03-03
  • Postman參數(shù)化實現(xiàn)過程及原理解析

    Postman參數(shù)化實現(xiàn)過程及原理解析

    這篇文章主要介紹了Postman參數(shù)化實現(xiàn)過程及原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • JS如何修改數(shù)組對象的Key和指定的值

    JS如何修改數(shù)組對象的Key和指定的值

    這篇文章主要介紹了JS如何修改數(shù)組對象的Key和指定的值,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-10-10
  • 微信小程序?qū)崿F(xiàn)選項卡的方法

    微信小程序?qū)崿F(xiàn)選項卡的方法

    這篇文章主要為大家詳細介紹了微信小程序?qū)崿F(xiàn)選項卡的方法,利用swiper組件實現(xiàn)選項卡功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • 完美解決spring websocket自動斷開連接再創(chuàng)建引發(fā)的問題

    完美解決spring websocket自動斷開連接再創(chuàng)建引發(fā)的問題

    下面小編就為大家?guī)硪黄昝澜鉀Qspring websocket自動斷開連接再創(chuàng)建引發(fā)的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • webpack css加載和圖片加載的方法示例

    webpack css加載和圖片加載的方法示例

    這篇文章主要介紹了webpack css加載和圖片加載的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • JavaScript實現(xiàn)簡單MD5加密的腳本分享

    JavaScript實現(xiàn)簡單MD5加密的腳本分享

    MD5信息摘要算法是一種被廣泛使用的密碼散列函數(shù),可以產(chǎn)生出一個128位(16字節(jié))的散列值(hash value),用于確保信息傳輸完整一致。本文將用JavaScript實現(xiàn)簡單MD5加密,感興趣的可以了解一下
    2022-10-10
  • javascript實現(xiàn)的時間格式加8小時功能示例

    javascript實現(xiàn)的時間格式加8小時功能示例

    這篇文章主要介紹了javascript實現(xiàn)的時間格式加8小時功能,涉及javascript日期時間轉(zhuǎn)換與運算相關(guān)操作技巧,需要的朋友可以參考下
    2019-06-06
  • ES6的異步操作之promise用法和async函數(shù)的具體使用

    ES6的異步操作之promise用法和async函數(shù)的具體使用

    這篇文章主要介紹了ES6的異步操作之promise用法和async函數(shù)的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12

最新評論

澜沧| 太湖县| 成武县| 商河县| 资阳市| 嵊州市| 汉源县| 凤凰县| 宜黄县| 西乡县| 亚东县| 应城市| 克什克腾旗| 芜湖市| 光泽县| 台北市| 阳原县| 永靖县| 渝中区| 菏泽市| 上虞市| 上蔡县| 家居| 丽江市| 紫金县| 五河县| 叙永县| 米泉市| 潞西市| 铜川市| 江源县| 宝丰县| 汉中市| 中牟县| 汨罗市| 聊城市| 柯坪县| 盐亭县| 定结县| 孝昌县| 奉节县|