// webpack4中除了正常安裝webpack以外,須要再單獨安一個webpack-cli npm i webpack webpack-cli -D
webpack <entry> [<entry>] <output>css
直接輸入webpack,默認執行: webpack.config.js or webpackfile.js文件;
若是想自定義文件名,運行:webpack --config webpack.conf.dev.jshtml
// ESmodule export default function(a,b){ return a+b } import sum from './sum' // common.js規範 module.exports = function(a,b){ return a-b } var minus = require('./minus') // AMD規範,多了兩個bundle,異步加載 //amd規範 define(function(require, factory) { 'use strict'; return function(a,b){ return a*b } }); require(['./muti'],function(muti){ console.log('muti,23,24='+muti(23,24)) }) console.log('sum,23,24='+sum(23,24)) console.log('minus,23,24='+minus(23,24))
npm install --save-dev babel-loader babel-core babel-preset-envnode
babel-loader:在import或加載模塊時,對es6代碼進行預處理,es6語法轉化爲es5語法。
babel-core:容許咱們去調用babel的api,能夠將js代碼分析成ast(抽象語法樹),方便各個插件分析語法進行相應的處理.
babel-preset-env:爲了告訴babel只編譯批准的內容,至關於babel-preset-es2015, es2016, es2017及最新版本。經過它可使用最新的js語法。jquery
module.exports = { entry:{ app:'./app.js' }, output:{ filename:'[name].[hash:5].js' }, module:{ rules:[ { test:/\.js$/, use:{ loader:'babel-loader', options:{ presets:[ // 最新的版本 ['@babel/preset-env',{ targets:{// 支持目標,數據來源於‘can i use’網站 browsers:['> 1%','last 2 versions'] //chrome:'52' } }] ] } }, //排除相關文件 exclude:'/node_modules/' } ] } }
其中,exclude是定義不但願babel處理的文件。targets是presets的一些預設選項,這裏表示將js用於瀏覽器,只確保佔比大於1%的瀏覽器的特性,主流瀏覽器的最新兩個主版本。
更多與配置有關的信息,能夠參考:
babel env preset設置,
browserlist預設置webpack
因爲babel-preset配置選項較多,咱們通常能夠在根目錄下創建.babelrc文件,專門用來放置babel preset配置,這是一個json文件。能夠將上述配置修改以下:git
//.bablerc文件 { "presets": [ ['env',{ "targets": { "browsers": ['> 1%', 'last 2 versions'] } }] ] } //原webpack.config.js文件 module: { rules: [ { test: /\.js$/, use: { loader: 'babel-loader' }, exclude: '/node_modules/' } ] }
在上面的babel配置中,babel只是將一些es6,es7-8的語法轉換成符合目標的js代碼,可是若是咱們使用一些特性或方法,好比Generator, Set, 或者一些方法。babel並不能轉換爲低版本瀏覽器識別的代碼。這時就須要babel-polifill。es6
簡單的說,polifill就是一個墊片,提供了一些低版本es標準對高級特性的實現。使用polifill的方法以下:github
npm install --save babel-polifill
而後在應用入口引入polifill,要確保它在任何其餘代碼/依賴聲明前被調用。web
//CommonJS module require('babel-polyfill'); //es module import 'babel-polifill';
在webpack.config.js中,將babel-polifill加入entry數組中:chrome
entry: ["babel-polifill", "./app.js"]
相比於runtime-transform,polifill用於應用開發中。會添加相應變量到全局,因此會污染全局變量。
更多配置參考:babel-polifill
完整代碼以下:
const path = require('path'); module.exports = { //entry爲入口,webpack從這裏開始編譯 entry: [ "babel-polyfill", path.join(__dirname, './src/index.js') ], //output爲輸出 path表明路徑 filename表明文件名稱 output: { path: path.join(__dirname, './bundle'), filename: 'bundle.js' }, //module是配置全部模塊要通過什麼處理 //test:處理什麼類型的文件,use:用什麼,include:處理這裏的,exclude:不處理這裏的 module: { rules: [ { test: /\.js$/, use: ['babel-loader'], include: path.join(__dirname , 'src'), exclude: /node_modules/ } ] }, };
runtime transform也是一個插件,它與polifill有些相似,但它不污染全局變量,因此常常用於框架開發。
安裝:
*npm install --save-dev babel-plugin-transform-runtime
npm install --save babel-runtime*
用法:
將下面內容添加到.bablerc文件中
{ "plugins": ["transform-runtime"] }
更多配置參考:bable-runtime-transform插件
1 . 安裝處理 css 相關 loader
// css-loader讓你能import css , style-loader能將css以style的形式插入 $ npm install --save-dev css-loader style-loader
module.exports = { plugins: [require('autoprefixer')] // 引用該插件便可了 }
而後在webpack裏配置postcss-loader
module.exports = { module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] } ] } }
2 . 安裝 less 相關
npm install --save-dev less less-loader
3 . 添加CSS3前綴
經過postcss中的autoprefixer能夠實現將CSS3中的一些須要兼容寫法的屬性添加響應的前綴,這樣省去咱們很多的時間
npm i postcss-loader autoprefixer -D
建立 postcss.config.js 加入如下代碼
module.exports = { plugins: { 'postcss-cssnext': {} } }
4 . 實現
src/app.css
body { background: pink; }
src/app.js
import css from './app.css'; console.log("hello world");
// 處理順序從右到左 less -> postcss -> css -> style { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }
5.用 mini-css-extract-plugin 把 CSS 分離成文件
npm install --save-dev mini-css-extract-plugin
rules: [ { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] } ] new MiniCssExtractPlugin({ filename: "[name].css",// 指定打包後的css chunkFilename: "[id].css" }),
6.壓縮與優化
打包 css 以後查看源碼,咱們發現它並無幫咱們作代碼壓縮,這時候須要使用 optimize-css-assets-webpack-plugin 這個插件,它不只能幫你壓縮 css 還能優化你的代碼。
npm install --save-dev optimize-css-assets-webpack-plugin
const optimizeCss = require('optimize-css-assets-webpack-plugin'); //配置 optimization: { minimizer: [new OptimizeCSSAssetsPlugin()]; }
如上圖測試用例所示,因爲optimize-css-assets-webpack-plugin這個插件默認使用了 cssnano 來做 css 優化,
因此它不只壓縮了代碼、刪掉了代碼中無用的註釋、還去除了冗餘的 css、優化了 css 的書寫順序,優化了你的代碼 margin: 10px 20px 10px 20px; =>margin:10px 20px;。同時大大減少了你 css 的文件大小。更多優化的細節見文檔。
安裝插件npm install --save-dev html-webpack-plugin 配置 webpack.config.js
npm install --save-dev html-webpack-plugin
const htmlWebpackPlugin = require('html-webpack-plugin'); ... plugins: [ new htmlWebpackPlugin({ filename: "index.html", //打包後的文件名 template: path.join(__dirname , "./src/index.html"), // 用哪一個html做爲模板,在src目錄下建立一個index.html頁面當作模板來用 hash: true, // 會在打包好的bundle.js後面加上hash串 }) ],
若是須要多頁面開發,能夠這樣寫:
let path = require('path'); let HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { // 多頁面開發,怎麼配置多頁面 entry: { index: './src/index.js', login: './src/login.js' }, // 出口文件 output: { filename: '[name].js', path: path.resolve('dist') }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', filename: 'index.html', chunks: ['index'] // 對應關係,index.js對應的是index.html }), new HtmlWebpackPlugin({ template: './src/login.html', filename: 'login.html', chunks: ['login'] // 對應關係,login.js對應的是login.html }) ] }
$ npm i clean-webpack-plugin --save-dev
const CleanWebpackPlugin = require('clean-webpack-plugin'); ... plugins: [ ... new CleanWebpackPlugin(['bundle']) //傳入清楚路徑 ]
在webpack4以前,提取公共代碼都是經過一個叫CommonsChunkPlugin的插件來辦到的。到了4之後,內置了一個如出一轍的功能,並且起了一個好聽的名字叫「優化」
下面咱們就來看看如何提取公共代碼
// 假設a.js和b.js都同時引入了jquery.js和一個寫好的utils.js // a.js和b.js import $ from 'jquery'; import {sum} from 'utils';
那麼他們兩個js中其中公共部分的代碼就是jquery和utils裏的代碼了
能夠針對第三方插件和寫好的公共文件
module.exports = { entry: { a: './src/a.js', b: './src/b.js' }, output: { filename: '[name].js', path: path.resolve('dust') }, // 提取公共代碼 + optimization: { splitChunks: { cacheGroups: { vendor: { // 抽離第三方插件 test: /node_modules/, // 指定是node_modules下的第三方包 chunks: 'initial', name: 'vendor', // 打包後的文件名,任意命名 // 設置優先級,防止和自定義的公共代碼提取時被覆蓋,不進行打包 priority: 10 }, utils: { // 抽離本身寫的公共代碼,utils這個名字能夠隨意起 chunks: 'initial', name: 'utils', // 任意命名 minSize: 0 // 只要超出0字節就生成一個新包 } } } + }, plugins: [ new HtmlWebpackPlugin({ filename: 'a.html', template: './src/index.html', // 以index.html爲模板 + chunks: ['vendor', 'a'] }), new HtmlWebpackPlugin({ filename: 'b.html', template: './src/index.html', // 以index.html爲模板 + chunks: ['vendor', 'b'] }) ] }
經過以上配置,能夠把引入到a.js和b.js中的這部分公共代碼提取出來,以下圖所示
安裝 webpack-dev-server
npm install --save-dev webpack-dev-server
webpack.config.js 添加配置
... devServer: { contentBase: path.join(__dirname, 'bundle'), //啓動路徑 host:'localhost', //域名,默認是localhost port: 8018, //端口號 open: true, //自動打開瀏覽器 hot: true //開啓熱更新 }
固然在npm run dev命令下,打包的文件存在於內存中,並不會產生在dist目錄下
配置devServer的時候,若是hot爲true,就表明開啓了熱更新
But這並沒那麼簡單,由於熱更新還須要配置一個webpack自帶的插件而且還要在主要js文件裏檢查是否有module.hot
下面就讓咱們直接看下代碼是如何實現的
// webpack.config.js let webpack = require('webpack'); module.exports = { plugins: [ // 熱更新,熱更新不是刷新 new webpack.HotModuleReplacementPlugin() ], devServer: { contentBase: './dist', hot: true, port: 3000 } } // 此時還沒完雖然配置了插件和開啓了熱更新,但實際上並不會生效 // index.js let a = 'hello world'; document.body.innerHTML = a; console.log('這是webpack打包的入口文件'); // 還須要在主要的js文件裏寫入下面這段代碼 if (module.hot) { // 實現熱更新 module.hot.accept(); }
$ npm install --save-dev file-loader
test: /\.(gif|png|jpe?g|svg)$/i, use: [ { loader: 'file-loader', options: { name: '[name].[ext]', // 文件名和擴展名 outputPath: 'images/' } },
npm i file-loader url-loader -D
module.exports = { module: { rules: [ { test: /\.css$/, use: ExtractTextWebpackPlugin.extract({ use: 'css-loader', publicPath: '../' }) }, { test: /\.(jpe?g|png|gif)$/, use: [ { loader: 'url-loader', options: { limit: 8192, // 小於8k的圖片自動轉成base64格式,而且不會存在實體圖片 outputPath: 'images/' // 圖片打包後存放的目錄 } } ] } ] } }
html-loader: html 變成導出成字符串的過程當中,還能進行壓縮處理(minimized)
$ npm install --save-dev html-loader
... { test: /\.(gif|png|jpe?g|svg)$/i, use: [ { loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'images/' } }, ] }, // 下面幾行纔是 html-loader 的配置內容 { test: /\.html$/, use: [ { loader: 'html-loader', options: { minimize: true } }], } ...
image-webpack-loader:壓縮圖片文件
$ npm install image-webpack-loader --save-dev
{ 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的配置中,resolve咱們經常使用來配置別名和省略後綴名
module.exports = { resolve: { // 別名 alias: { $: './src/jquery.js' }, // 省略後綴 extensions: ['.js', '.json', '.css'] }, }
webpack 4 在項目中實際測了下,廣泛能提升 20%~30%的打包速度。
首先你須要知道你目前打包慢,是慢在哪裏。
咱們能夠用 speed-measure-webpack-plugin 這個插件,它能監控 webpack 每一步操做的耗時。以下圖:
能夠看出其實大部分打包花費的時間是在Uglifyjs壓縮代碼。和前面的提高熱更新的切入點差很少,查看source map的正確與否,exclude/include的正確使用等等。