#### SCSS
```
use: ['style-loader', 'css-loader', 'sass-loader']
```
* 通過sass-loader將scss轉換為css
* 通過css-loader找出@import\import\url()這樣的css導入語句,模塊化、壓縮化等等操作之后再將其交給style-loader
* 最后用style-loader將樣式變成js的字符串,動態將內容插入到head的style標簽中
#### 為單頁應用生成HTML(web-webpack-plugin)
該插件能夠生成html文件,比html-webpack-plugin更好用
```
{
entry: {
app: './main.js'
},
output: {
filename: '[name]_[chunkhash:8].js',
path: path.resolve(__dirname, './dist')
},
module: {/*一系列loader和css抽取*/},
plugins: [
new WebPlugin({
template: './template.html',
filename: 'index.html'
}),
new ExtractTextPlugin({
filename: '[name]_[contenthash:8].css'
})
]
}
//template.html
<head>
<!--來自名叫app的chunk,inline代表將其插入到這里-->
<link rel="stylesheet" href="app?_inline" />
</head>
<body>
...
<!--不一定非得是webpack里的chunk,本地文件也可以。意思是:將路徑下的文件內容插入到這里-->
<script src="./common/test.js?_inline"></script>
<script src="app"></script>
</body>
```
最終變成了
```
<head>
<style>
app chunk里的內容
</style>
</head>
<body>
...
<script>
./common/test.js里的內容
</script>
<script src="app_746f32b2.js"></script>
</body>
```
#### 管理多頁應用
類似于angular-m-cli,現在已經有了插件:AutoWebPlugin
規定了目錄結構
```
pages
----index
----index.css
----index.js
----login
----index.css
----index.js
common.css
test.js
tempate.html
```
```
const autoWebPlugin = new AutoWebPlugin('pages', {
template: './template.html',
postEntrys: ['./common.css'],
commonsChunk: {
name: 'app'
}
})
module.exports = {
entry: autoWebPlugin.entry({
//...
}),
plugins: [autoWebPlugin]
}
```
```
<head>
<!--style的注入位置-->
<!--STYLE-->
</head>
<body>
<script src="./common/test.js?_inline"></script>
<!--script的注入位置-->
<!--SCRIPT-->
</body>
```
結果
```
<head>
<!--style的注入位置-->
<link rel="stylesheet" href="common_7cc98ad0.css"/>
<link rel="stylesheet" href="login_e31e214b.css"/><!--頁面自己的css-->
</head>
<body>
<script src="./common/test.js?_inline"></script>
<!--script的注入位置-->
<script>
./common/test.js里的內容
</script>
<script src="app_a1d9142f.js"></script>
<script src="login_f926c4e6.js"></script>
</body>
```
由于模板html被當做項目的所有頁面的html,因此引入的css和js的名字就不能是寫死了的,而是用<!--STYLE-->和<!--SCRIPT-->來當做插槽。
#### 構建NPM模塊
發布到npm的模塊大多都是commonJS規范。es6或jsx代碼不僅要轉換成es5,還要支持commonJS規范。
以react為例
```
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports {
entry: './src/index.js',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'lib'),
libraryTarget: 'commonjs2' //輸出的代碼符合commonJS2規范,以便其他模塊使用
},
externals: /^(react|babel-runtime)/, //不要把react和babel-runtime打包進來
module: {
rules: [{
test: /\.js$/,
use: ['babel-loader'],
exclude: /node_modules/
}, {
test: /\.css/,
use: ExtractTextPlugin.extract({
use: ['css-loader']
})
}]
},
plugins: [
new ExtractTextPlugin({
filename: 'index.css',
})
],
devtool: 'source-map'
}
```
```
//.babelrc
//babel會在每個輸出文件中內嵌babel的輔助函數。
//為了防止冗余,使用babel-plugin-transform-runtime插件
//npm i babel-plugin-transform-runtime -D
//npm i babel-runtime -S
{
"plugins": [[
"transform-runtime", {
"polyfill": false
}
]]
}
```
#### 代碼檢查
```
npm i eslint-loader
npm i stylelint-webpack-plugin
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
enforce: 'pre' //將eslint-loader的執行順序放在最前面
}
]
plugins: [new StyleLintPlugin()]
```
使用代碼檢查會導致構建速度變慢,建議只在開發環境下使用。
#### 加載圖片
```
npm i url-loader
npm i file-loader
//30kb一下直接以dataURL的形式寫入,否則外部引入
{
test: /\.png$/,
use: [{
loader: 'url-loader',
options: {
limit: 1024 * 30, //也就是30kb
fallback: 'file-loader'
}
}]
}
```
#### Source Map
* eval:用eval包裹需要安裝的模塊
* source-map:生成獨立的source map文件
* hidden:不在js中指出source map文件的存在,使得瀏覽器不會去加載它
* inline:base64的形式直接注入到js中
* cheap:生產的cource map不會包含列信息以減小計算量,生成的文件更小
* module:來自loader的source map被簡單處理成每行一個模塊
如何取舍?
source-map雖然輸出質量最高,但也是最慢的,且源碼全部暴露
* 開發環境下:使用cheap-module-eval-source-map,因為速度最快,因為一般的開發環境不用壓縮代碼,即使沒有列信息也不影響debug
* 生產環境下:使用hidden-source-map,意思是生成的最詳細的source map但不會將其暴露出去。