webpack4.0剛剛發佈,官網自稱4.0最大的特色就是零配置。本文就詳細介紹一下webpack4.0實戰那些事兒。javascript
打包機
WebPack能夠看作是模塊打包機:它作的事情是,分析你的項目結構,找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),並將其打包爲合適的格式以供瀏覽器使用。css
構建
構建就是把源代碼轉換成發佈到線上的可執行 JavaScrip、CSS、HTML 代碼,包括以下內容。html
構建實際上是工程化、自動化思想在前端開發中的體現,把一系列流程用代碼去實現,讓代碼自動化地執行這一系列複雜的流程。 構建給前端開發注入了更大的活力,解放了咱們的生產力。前端
npm init -y
在要進行打包的目錄下初始化npm, 在控制檯執行以上命令後會生成一個package.json
的文件。java
npm install webpack webpack-cli -D
由於從4.0開始,webpack拆分開兩個包分別是webpack
和webpack-cli
node
webpack.config.js
module.exports = { entry:配置入口文件的地址 output:配置出口文件的地址 module:配置模塊,主要用來配置不一樣文件的加載器 plugins:配置插件 devServer:配置開發服務器 }
接下來咱們就一一介紹一下它們的配置。react
npm install webpack-dev-server -D
devServer:{ contentBase:path.resolve(__dirname,'dist'),// 配置開發服務運行時的文件根目錄 host:'localhost',// 開發服務器監聽的主機地址 compress:true, // 開發服務器是否啓動gzip等壓縮 port:8080 // 開發服務器監聽的端口 }
"scripts": { "dev": "webpack-dev-server --open --mode development " }
note
從4.0開始,運行webpack時必定要加參數 --mode development
或者--mode production
,分別對應開發環境和生產環境。jquery
module
loader
module
主要用來配置不一樣文件的加載器。談到加載就離不開loader
,那什麼是loader
呢?webpack
loader的概念
經過使用不一樣的Loader,Webpack能夠要把不一樣的文件都轉成JS文件,好比CSS、ES6/七、JSX等。git
test
:匹配處理文件的擴展名的正則表達式use
:loader名稱,就是你要使用模塊的名稱include/exclude
:手動指定必須處理的文件夾或屏蔽不須要處理的文件夾query
:爲loaders提供額外的設置選項
loader
的三種寫法
install
npm install style-loader css-loader -D
配置加載器
module: { rules:[ { test:/\.css$/, use:['style-loader','css-loader'], include:path.join(__dirname,'./src'), exclude:/node_modules/ } ] }
note
注意:加載器的加載順序爲從右至左。即先用css-loader
解析而後用style-loader
將解析後的css
文件添加到Head
標籤中。
install
npm install file-loader url-loader html-withimg-loader -D
file-loader
解決CSS等文件中的引入圖片路徑問題url-loader
當圖片較小的時候會把圖片BASE64編碼,大於limit參數的時候仍是使用file-loader 進行拷貝配置加載器
{ test: /\.(png|jpg|gif|svg|bmp|eot|woff|woff2|ttf)$/, loader: { loader: 'url-loader', options: { limit: 5 * 1024,// 圖片大小 > limit 使用file-loader, 反之使用url-loader outputPath: 'images/'// 指定打包後的圖片位置 } } }
usage - 手動添加圖片
let logo = require('./images/logo.png'); let img = new Image(); img.src = logo; document.body.appendChild(img);
usage - 在CSS中引入圖片
.img-bg{ background: url(./images/logo.png); width:173px; height:66px; }
usage - 在HTML中使用圖片
{ test:/\.(html|html)$/, use:'html-withimg-loader', include:path.join(__dirname,'./src'), exclude:/node_modules/ }
npm install less less-loader node-sass sass-loader -D
把編譯好的代碼放到head裏面
{ test: /\.css$/, loader: ['style-loader', 'css-loader'] }, { test: /\.less$/, loader: ['style-loader', 'css-loader'] }, { test: /\.scss$/, loader: ['style-loader', 'css-loader'] }
把編譯好的代碼放到單獨的文件裏面
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin'); let cssExtract = new ExtractTextWebpackPlugin('css.css'); let lessExtract = new ExtractTextWebpackPlugin('less.css'); let sassExtract = new ExtractTextWebpackPlugin('sass.css'); ... { test: /\.css$/, loader: cssExtract.extract({ use: ['css-loader?minimize'] }) }, { test: /\.less$/, loader: lessExtract.extract({ use: ['css-loader?minimize', 'less-loader'] }) }, { test: /\.scss$/, loader: sassExtract.extract({ use: ['css-loader?minimize', 'sass-loader'] }) }
爲了瀏覽器的兼容性,有時候咱們必須加入-webkit,-ms,-o,-moz這些前綴
install
npm install postcss-loader autoprefixer -D
usage
postcss-loader
須要配置 postcss.config.js
文件,postcss.config.js 內容以下:
module.exports = { plugins: [ require('autoprefixer') ] }
// 把 post-laoder push 到css的loader數組中 { test: /\.css$/, loader: ['style-loader', 'css-loader', 'postcss-loader'] }, { test: /\.less$/, loader: ['style-loader', 'css-loader', 'less-loader'] }, { test: /\.scss$/, loader: ['style-loader', 'css-loader', 'sass-loader'] }
Babel實際上是一個編譯JavaScript的平臺,能夠把ES6/ES7,React的JSX轉義爲ES5。
install
npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 babel-preset-react -D
配置加載器
{ test:/\.jsx?$/, use: { loader: 'babel-loader', options: { presets: ["env","stage-0","react"]// env --> es6, stage-0 --> es7, react --> react } }, include:path.join(__dirname,'./src'), exclude:/node_modules/ }
plugins
配置插件
咱們但願自動能產出HTML文件,並在裏面引入產出後的資源。
install
npm install html-webpack-plugin -D
usage
const HtmlWebpackPlugin = require('html-webpack-plugin'); plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', // 指定產出的模板 filename: 'base.html', // 產出的文件名 chunks: ['common', 'base'], // 在產出的HTML文件裏引入哪些代碼塊 hash: true, // 名稱是否哈希值 title: 'base', // 能夠給模板設置變量名,在html模板中調用 htmlWebpackPlugin.options.title 能夠使用 minify: { // 對html文件進行壓縮 removeAttributeQuotes: true // 移除雙引號 } }) ]
由於CSS的下載和JS能夠並行,當一個HTML文件很大的時候,咱們能夠把CSS單獨提取出來加載
install
npm install extract-text-webpack-plugin@next -D
usage
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin'); let cssExtract = new ExtractTextWebpackPlugin('css.css'); let lessExtract = new ExtractTextWebpackPlugin('less.css'); let sassExtract = new ExtractTextWebpackPlugin('sass.css'); ... module: { rules: [ { test: /\.css$/, loader: cssExtract.extract({ use: ['css-loader?minimize'] }) }, { test: /\.less$/, loader: lessExtract.extract({ use: ['css-loader?minimize', 'less-loader'] }) }, { test: /\.scss$/, loader: sassExtract.extract({ use: ['css-loader?minimize', 'sass-loader'] }) } ] } ... plugins: [ cssExtract, lessExtract, sassExtract ]
處理圖片路徑問題
const PUBLIC_PATH='/'; output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', publicPath:PUBLIC_PATH }
有時項目中沒有引用的文件也須要打包到目標目錄
install
npm install copy-webpack-plugin -D
usage
const CopyWebpackPlugin = require('copy-webpack-plugin'); plugins: [ new CopyWebpackPlugin([{ from: path.join(__dirname, 'public'), // 從哪裏複製 to: path.join(__dirname, 'dist', 'public') // 複製到哪裏 }]) ]
install
npm install clean-webpack-plugin -D
usage
const CleanWebpackPlugin = require('clean-webpack-plugin'); plugins: [ new CleanWebpackPlugin([path.join(__dirname, 'dist')]) ]
install
npm install uglifyjs-webpack-plugin -D
usage
onst UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin'); plugins: [ new UglifyjsWebpackPlugin() ]
webapck經過配置能夠自動給咱們source maps文件,map文件是一種對應編譯文件和源文件的方法
usage
devtool:'eval-source-map'
devtool的參數詳解
source-map
把映射文件生成到單獨的文件,最完整最慢cheap-module-source-map
在一個單獨的文件中產生一個不帶列映射的Mapeval-source-map
使用eval打包源文件模塊,在同一個文件中生成完整sourcemapcheap-module-eval-source-map
sourcemap和打包後的JS同行顯示,沒有映射列import _ from 'lodash'; alert(_.join(['a','b','c'],'@'));
new webpack.ProvidePlugin({ _:'lodash' })
當代碼發生修改後能夠自動從新編譯
watch: true, watchOptions: { ignored: /node_modules/, //忽略不用監聽變動的目錄 aggregateTimeout: 500, // 文件發生改變後多長時間後再從新編譯(Add a delay before rebuilding once the first file changed ) poll:1000 //每秒詢問的文件變動的次數 }
若是你有單獨的後端開發服務器 API,而且但願在同域名下發送 API 請求 ,那麼代理某些 URL 會頗有用。
//請求到 /api/users 如今會被代理到請求 http://localhost:9000/api/users。 proxy: { "/api": "http://localhost:9000", }
指定extension以後能夠不用在require或是import的時候加文件擴展名,會依次嘗試添加擴展名進行匹配
resolve: { //自動補全後綴,注意第一個必須是空字符串,後綴必定以點開頭 extensions: ["",".js",".css",".json"], },
配置別名能夠加快webpack查找模塊的速度
const bootstrap = path.join(__dirname,'node_modules/bootstrap/dist/css/bootstrap.css'); resolve: { alias: { 'bootstrap': bootstrap } }
install
npm install expose-loader -D
action
把模塊的導出暴露給全局變量,
usage-1
require("expose-loader?libraryName!./file.js");
usage-2
rules: [{ test: require.resolve('jquery'),// 注意 這裏是require的resolve 方法 use: { loader: "expose-loader", options: "$" } }]
有時候咱們的頁面能夠不止一個HTML頁面,會有多個頁面,因此就須要多入口
usage
// 多個入口,能夠給每一個入口添加html模板 entry: { index: './src/index.js', main:'./src/main.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[hash].js', publicPath:PUBLIC_PATH }, plugins: [ new HtmlWebpackPlugin({ minify: { removeAttributeQuotes:true }, hash: true, template: './src/index.html', chunks:['index'], filename:'index.html' }), new HtmlWebpackPlugin({ minify: { removeAttributeQuotes:true }, hash: true, chunks:['login'], template: './src/login.html', filename:'login.html' })] ]
若是咱們想引用一個庫,可是又不想讓webpack打包,而且又不影響咱們在程序中以CMD、AMD或者window/global全局等方式進行使用,那就能夠經過配置externals。
webpack.config.js
externals: { jquery: "jQuery" //若是要在瀏覽器中運行,那麼不用添加什麼前綴,默認設置就是global },
index.js
const $ = require("jquery"); const $ = window.jQuery;