說是解決方案實際上更像是webpack的插件索引。
寫這一篇的目的是爲了造成一個索引,未來要用時直接來查找便可。css
解決方案:使用插件 html-webpack-plugin
webpack.config.js以下:html
module.exports = { entry: './src/app.js', output: { path: __dirname + '/dist', filename: 'app.bundle.js' }, plugins: [new HtmlWebpackPlugin({ template: './src/模板文件.html', filename: '構建的.html', minify: { collapseWhitespace: true, }, hash: true, })] };
注意要有path,由於這個輸出的html須要知道輸出目錄node
loader用於對模塊的源代碼進行預處理轉換。react
解決方案:使用css-loader,style-loaderlinux
看一下項目結構:
webpack
此時運行webpack命令會拋出錯誤:
git
接下來安裝 css-loader 和 style-loaderes6
npm install --save-dev css-loader style-loader
再修改webpack.config.js爲:
github
這其中rules數組就是loader用來的匹配和轉換資源的規則數組。
test表明匹配需轉換文件的正則表達式,而圖中表示匹配全部以css結尾的文件。
而use數組表明用哪些loader去處理這些匹配到的文件。web
此時再運行webpack,打包後的文件bundle.js就包含了css代碼。
其中css-loader負責加載css,打包css到js中。
而style-loader負責生成:在js運行時,將css代碼經過style標籤注入到dom中。
解決方案:使用less-loader
可是用less-loader只是將LESS代碼轉換爲css代碼。若是要打包文件到js中,仍是須要用到上面提到的css-loader和style-loader。
看一下項目結構:
而後app.js的代碼爲:
import styles from './app.less'; console.info('我是一個js文件123')
爲了解決這種狀況,首先要安裝 less-loader,而less-loader是基於less的,因此也要安裝less。
npm i --save-dev less less-loader
修改webpack.config.js爲:
module: { rules: [ { test: /\.less$/, use: [ 'style-loader', 'css-loader', 'less-loader' ] } ] }
不少時候咱們想要的效果並非想要把幾個LESS或者CSS處理好後,打包到一個js中,而是想要把它打包到一個css文件中。
此時就有了插件 extract-text-webpack-plugin。
首先進行安裝
npm i --save-dev extract-text-webpack-plugin
而後修改webpack.config.js爲:
與原配置對比能夠發現,比html-webpack-plugin這個插件多作了一步,就是在匹配和轉換規則裏面的use中使用了ExtractTextPlugin.extract。
注意這裏的fallback表示,在提取文件失敗後,將繼續使用style-loader去打包到js中。
此時運行webpack
能夠發現輸出目錄build下生成了一個style.css文件,也就是咱們在webpack.config.js中指望生成的文件,而且在生成的demo.html中被引用了。
webpack-dev-server能夠在本地搭建一個簡單的開發環境用的服務器,自動打開瀏覽器,並且還能夠達到webpack -watch的效果。
首先安裝一下:
npm i -g webpack-dev-server npm i --save-dev webpack-dev-server
這裏不須要改動webpack.config.js,直接運行命令
webpack-dev-server
查看控制檯輸出:
顯示項目運行在http://localhost:8080/
webpack的輸出目錄的路徑在/下面
而且這個服務器會自動識別輸出目錄下名爲index的HTML文件,而咱們以前輸出的文件名爲demo.html。
因此還須要將以前html-webpack-plugin中配置的filename改成index.html,或者直接用http://localhost:8080/demo.html也行。
當咱們修改了源代碼後,打開的網頁還會自動更新。
爲了更靈活的應用開發環境的服務器,也能夠在webpack.config.js中加入以下代碼:
devServer配置 | 功能 |
---|---|
port | 修改端口爲8787,而不是默認的8080。 |
open | 爲true表示會自動打開瀏覽器,而不是須要咱們再手動打開瀏覽器並在裏面輸入http://localhost:8080。 |
compress | 對本地server返回的文件提供gzip壓縮 |
index | 指定網站首頁映射的文件,默認爲index.html |
這裏說是ES6,實際上能夠認爲是ECMAScript的高版本代碼,只是代指而已。
babel的做用是將瀏覽器還未支持的這些高版本js代碼轉換成能夠被指定瀏覽器支持的js代碼。
這裏列出能夠轉換的大體語法:
那麼首先就須要安裝babel
npm install babel-core babel-preset-env --save-dev
而後,爲了和webpack結合起來,要用到babel-loader
npm install babel-loader --save-dev
而後在webpack.config.js的rules數組中增長如下代碼:
{ test: /\.js$/, exclude: /(node_modules)/, use: { loader: 'babel-loader', options: { presets: ['env'] } } }
這行代碼的意思是用babel-loader解析除了node_modules文件下的全部js文件。
而babel-loader就是用babel去解析js代碼。
options的內容相似於.babelrc文件的配置,有了這個就不須要.babelrc文件了。
presets表示預處理器,如今的babel不像之前須要不少預處理器了,只須要env這一個就夠了。
修改以前的app.js中的代碼爲:
console.info('我是一個js文件123') const doSomething=() => { console.info('do do do') }
使用webpack命令後,能夠看到咱們最後的打包js文件中代碼變成了這樣:
如下爲這些新增函數:
安裝:
npm install --save-dev babel-polyfill
爲了確保babel-polyfill被最早加載和解析,因此通常都是講babel-polyfill在最開始的腳本中引入。
而在webpack中,就是在放到entry中,因此須要修改webpack.config.js中的配置爲:
安裝
npm install --save-dev babel-preset-react
配置:
這裏是匹配全部以js或者jsx結尾的文件,並用 babel-preset-env和babel-preset-react進行解析
這裏首先介紹一下nodejs的path模塊的一個功能:resolve。
將相對路徑轉換爲絕對路徑。
在最開始引用path模塊
var path = require('path');
而後能夠在輸出設置那裏修改代碼爲:
output: { path: path.resolve(__dirname, 'build'), filename: 'bundle.js' },
和咱們原來的代碼沒有任何區別。
hash和chunkhash有區別,hash的話輸出的文件用的都是同一個hash值,而chunkhash的話是根據模塊來計算的,每一個輸出文件的hash值都不同。
直接將輸出文件改成
output: { path: path.resolve(__dirname, 'build'), filename: 'bundle.[chunkhash].js' },
[chunkhash]就表明一串隨機的hash值
當咱們像上面同樣不斷改變輸出文件時,以前的輸出文件並無去掉。
爲了解決這個問題就須要clean-webpack-plugin。
首先安裝
npm i clean-webpack-plugin --save-dev
而後引用插件,並聲明每次生成輸出須要清空的文件夾
var CleanWebpackPlugin = require('clean-webpack-plugin'); var pathsToClean = [ 'build', ]
再在插件配置中加入:
new CleanWebpackPlugin(pathsToClean)
以前的webpack-dev-server提供了監聽功能,只要代碼改變,瀏覽器就會刷新。
可是模塊熱替換是不會刷新瀏覽器,只刷新修改到的那部分模塊。
模塊熱替換無需安裝。
首先須要引入模塊
var webpack = require('webpack')
其實插件中加入:
new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin()
此時運行webpack可能會報錯,咱們須要把以前在輸出環境中寫的[chunkhash]改成[hash]
能夠在腳本中這麼寫:
"scripts": {
"dev": "webpack-dev-server",
"prod": "set NODE_ENV=production && webpack -p"
},
這樣在webpack.config.js中這樣修改上面的東西:
if (isProduction) { config.output.filename = 'bundle.[chunkhash].js' } else { config.plugins.push(new webpack.NamedModulesPlugin()) config.plugins.push(new webpack.HotModuleReplacementPlugin()) }
這樣就能夠根據環境的不一樣來運行不一樣的配置
上述設置環境變量的腳本中只有在window下才有效,在linux和mac上須要使用
"prod": "NODE_ENV=production webpack -p"
爲了解決這個問題,使得不一樣平臺的人能公用一套代碼,咱們可使用cross-env。
首先進行安裝:
npm i --save-dev cross-env
而後命令直接使用相似於mac上的用法便可
"prod": "cross-env NODE_ENV=production webpack -p"
file-loader能夠用來處理圖片和字體文件在css文件中的路徑問題,輸出的css文件中會引用輸出的文件地址。
html-loader能夠用來處理html中,好比img元素的圖片路徑問題。
首先安裝
npm i --save-dev file-loader html-loader
配置:
{ test: /\.(gif|png|jpe?g|svg)$/i, use: { loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'src/images/' } } }, { test: /\.html$/, use: [{ loader: 'html-loader', options: { minimize: true } }], }
安裝:
npm i --save-dev image-webpack-loader
配置:
{ test: /\.(gif|png|jpe?g|svg)$/i, use: [{ loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'images/' } }, { loader: 'image-webpack-loader', options: { bypassOnDebug: true, } } ] },
這裏的options中也能夠具體配置各個圖片類型的壓縮質量
若是咱們用web-dev-server運行咱們的輸出文件,發現其中有些BUG,而後打開開發者工具取定位文件的時候,只會定位到咱們的輸出文件。
而這些輸出文件是通過處理的,咱們只有找到咱們的源文件代碼,而後進行相應的修改才能解決問題。
因而這裏咱們須要用到source-map。
很簡單,在webpack.config.js中加入以下配置便可:
devtool: 'source-map',
就這麼簡單,還不須要安裝什麼插件。
可是這隻對js有效,若是咱們的css出現錯誤了呢,答案就是以下配置:
以前咱們經過在命令中設置環境變量,而且經過環境變量來判斷環境來進行不一樣的配置。
如今咱們用官方推薦的方法來分離生產環境和開發環境的配置文件。
咱們將webpack.config.js分爲三個文件
其中webpack.common.config.js爲生產環境和開發環境共有的配置,dev爲開發環境獨有的配置,prod爲生成環境獨有的配置。
而想要合成真正的配置文件,還須要一個工具:webpack-merge。
npm install --save-dev webpack-merge
如下是咱們以前的webpack.config.js代碼:
var ExtractTextPlugin = require('extract-text-webpack-plugin') var HtmlWebpackPlugin = require('html-webpack-plugin') var CleanWebpackPlugin = require('clean-webpack-plugin') var path = require('path') var webpack = require('webpack') var pathsToClean = [ 'build', ] var isProduction = process.env.NODE_ENV === 'production' var config = { entry: ['babel-polyfill', './src/app.js'], output: { path: path.resolve(__dirname, 'build'), filename: '[name].[hash].js' }, devtool: 'source-map', devServer: { port: 8787, open: true, compress: true, index: 'demo.html' }, plugins: [ new HtmlWebpackPlugin({ template: './template/index.html', filename: 'demo.html', minify: { collapseWhitespace: true, }, hash: true }), new ExtractTextPlugin({ filename: 'style.css', allChunks: false }), new CleanWebpackPlugin(pathsToClean) ], module: { rules: [{ test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader?sourceMap'] }) }, { test: /\.less$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader?sourceMap', 'less-loader?sourceMap'] }) }, { test: /\.jsx?$/, exclude: /(node_modules)/, use: { loader: 'babel-loader', options: { presets: ['env', 'react'] } } }, { test: /\.(gif|png|jpe?g|svg)$/i, use: [{ loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'images/' } }, { loader: 'image-webpack-loader', options: { bypassOnDebug: true, } } ] }, { test: /\.html$/, use: [{ loader: 'html-loader', options: { minimize: true } }], } ] } }; if (isProduction) { config.output.filename = '[name].[chunkhash].js' } else { config.plugins.push(new webpack.NamedModulesPlugin()) config.plugins.push(new webpack.HotModuleReplacementPlugin()) } module.exports = config
接下來分爲三個文件,webpack.common.js:
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var CleanWebpackPlugin = require('clean-webpack-plugin')
var path = require('path')
var webpack = require('webpack')
var pathsToClean = [ 'build', ] var isProduction = process.env.NODE_ENV === 'production' module.exports = { entry: ['babel-polyfill', './src/app.js'], output: { path: path.resolve(__dirname, 'build'), filename: '[name].[chunkhash].js' }, plugins: [ new HtmlWebpackPlugin({ template: './template/index.html', filename: 'demo.html', minify: { collapseWhitespace: true, }, hash: isProduction }), new ExtractTextPlugin({ filename: '[name].[contenthash].css', allChunks: false }), new CleanWebpackPlugin(pathsToClean) ], module: { rules: [{ test: /\.jsx?$/, exclude: /(node_modules)/, use: { loader: 'babel-loader', options: { presets: ['env', 'react'] } } }, { test: /\.(gif|png|jpe?g|svg)$/i, use: [{ loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'images/' } }, { loader: 'image-webpack-loader', options: { bypassOnDebug: true, } } ] }, { test: /\.html$/, use: [{ loader: 'html-loader', options: { minimize: true } }], } ] } };
而後是webpack.dev.js:
const merge = require('webpack-merge'); const common = require('./webpack.common.js'); const webpack = require('webpack'); const ExtractTextPlugin = require('extract-text-webpack-plugin') module.exports = merge(common, { output: { filename: '[name].[hash].js' }, devtool: 'source-map', devServer: { port: 8787, open: true, compress: true, index: 'demo.html' }, plugins: [ new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin() ], module: { rules: [{ test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader?sourceMap'] }) }, { test: /\.less$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader?sourceMap', 'less-loader?sourceMap'] }) } ] } });
最後是webpack.prod.js:
const merge = require('webpack-merge'); const common = require('./webpack.common.js'); const ExtractTextPlugin = require('extract-text-webpack-plugin') module.exports = merge(common, { module: { rules: [{ test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader'] }) }, { test: /\.less$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader', 'less-loader'] }) } ] } });
而後修改一下package.json中的腳本便可
"scripts": { "dev": "webpack-dev-server --config webpack.dev.js", "prod": "cross-env NODE_ENV=production webpack -p --config webpack.prod.js" },
安裝:
npm install --save-dev webpack-bundle-analyzer
而後修改webpack.config.js:
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); module.exports = merge(common, { // ... plugins: [ new BundleAnalyzerPlugin({ analyzerPort: 8919 }) ], });
這裏的analyzerPort爲打包後的本地展現網頁的端口,默認是8888。
而後webpack便可。
效果圖以下:
各個插件以及loader的玩法還有不少,這裏不具體介紹。