安裝本地的webpackcss
yarn add webpack webpack-cli -D
複製代碼
npx webpack
npx webpack --mode production // 默認爲生產環境 會進行壓縮打包
npx webpack --mode development
複製代碼
webpack_require 至關因而webpack本身實現的一套模塊化的機制html
默認配置文件名稱爲 webpack.config.jsvue
module.exports = {
mode: 'development', // 模式 默認兩種 production development
entry: './src/index.js', // 入口
output: {
filename: 'bundle.[hash:8].js', // 出口 [hash:8]顯示8位hash值
path: path.resolve(__dirname, 'build') // path必須是一個絕對路徑 path.resolve幫咱們把相對路徑解析成絕對路徑
},
}
複製代碼
在webpack-cli/bin/config-yargs中能夠看到有這樣一行 defaultDescription: "webpack.config.js or webpackfile.js" 即配置文件名稱爲webpack.config.js or webpackfile.js 固然咱們也能夠手動指定配置文件的名稱node
npx webpack --config filename
複製代碼
也能夠經過在package.json中的script裏配置jquery
"scripts":{
"build": "webpack --config webpack.config.js" // webpack.config.js可改成自定義文件名
},
複製代碼
npm run build
複製代碼
若是必定要手動傳參也能夠經過多加兩個-webpack
"scripts":{
"build": "webpack" // webpack.config.js可改成自定義文件名
},
複製代碼
npm run build -- --config webpack.config.js
複製代碼
到目前爲止,咱們的配置依然很弱,只能打包js文件,接下來咱們繼續添加更多的配置es6
下面咱們但願可以經過http://localhost 這樣的方式來啓動一個服務, 咱們能夠經過webpack內置的一個服務 webpack-dev-server (內部是經過express實現的)web
yarn add webpack-dev-server -D
複製代碼
如今咱們能夠經過express
npx webpack-dev-server
複製代碼
固然也一樣能夠經過package.json設置npm
"scripts": {
"dev": "webpack-dev-server",
"build": "webpack --config webpack.config.js"
},
複製代碼
而後執行
npm run dev
複製代碼
同時咱們能夠給在webpack.config.js中對webpack-dev-server進行配置
devServer: { // 開發服務器的配置
port: '3000',
progress: true,
contentBase: './build',
open: true
},
複製代碼
指望:動態生成build/index.html, 並把打包後的文件引入到index.html
在src目錄下建index.html,這時咱們須要使用插件HtmlWebpackPlugin,plugin的用法大都相同,HtmlWebpackPlugin是一個類,new一下就能夠了
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // template文件
filename: 'index.html', // 生成的template文件名稱 默認爲index.html
hash: true, // 在生成的html中添加引用hash
minify: {
removeAttributeQuotes: true, // 去除雙引號
collapseWhitespace: true, // 去除空行
}
}),
],
複製代碼
到這裏能夠看到咱們既能夠經過在配置output的時候經過filename: bundle.[hash:8].js 來給生成文件添加hash,也能夠經過HtmlWebpackPlugin的配置hash來實現,二者添加hash的方式分別爲 bundle.12345678.js和 bundle?12345678
而經過filename: bundle.[hash:8].js這種方式實現,咱們還須要再作一步,就是在每次從新打包的時候把舊的文件刪除 // todo
咱們知道,webpack默認只支持js模塊,那麼咱們怎麼處理css/less/scss等模塊呢?這時候就須要loader上場了
You may need an appropriate loader to handle this file type.
複製代碼
module: { // 模塊
rules: [ // 規則
// css-loader 主要用來解析@import這種語法
// style-loader 把樣式插入頁面
// loader特色,功能單一 多個loader能夠協做
// 一個loader可使用字符串,多個可使用數組, 須要傳入參數時可使用對象方式
// loader的順序,默認爲從右向左, 從下到上執行 webpack選擇了compose方式
// {
// test: '/\.css$/', use: [
// { loader: 'css-loader', options: {} } // 對象方式
// ]
// },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
]
},
複製代碼
less、sass文件同理, 以scss文件爲例:
{
test: /\.css$/, use: [
{ loader: 'style-loader', options: { insertAt: 'top' } }, // 對象方式 insertAt插入位置
{ loader: 'css-loader', options: {} },
]
},
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
複製代碼
webpack4中,css抽離須要插件 mini-css-extract-plugin (注意再也不是extract-text-webpack-plugin)
new miniCssExtractPlugin({
filename: 'main.css', // 抽離出的css的文件名
}),
複製代碼
同時在module.rules中作以下修改以免重複插入:
- // { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
+ { test: /\.scss$/, use: [miniCssExtractPlugin.loader, 'css-loader', 'sass-loader'] },
複製代碼
咱們可使用postcss-loader autoprefixer來實現
- // { test: /\.scss$/, use: [miniCssExtractPlugin.loader, 'css-loader', 'sass-loader'] },
+ { test: /\.scss$/, use: [miniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'] },
複製代碼
在根目錄下新建postcss.config.js
module.exports = {
plugins: [
require('autoprefixer'), // 自動添加前綴
]
}
複製代碼
此時咱們設置mode爲production,發現js和html都已是壓縮過的了,但是css文件卻沒有。咱們這裏引入另一個插件:optimize-css-assets-webpack-plugin來優化css資源
let OptimizeCss = require('optimize-css-assets-webpack-plugin');
plugins: [
...,
new OptimizeCss(),
]
複製代碼
固然咱們也能夠經過uglifyjs-webpack-plugin來壓縮咱們的js文件
let UglifyjsPlugin = require('uglifyjs-webpack-plugin');
plugins: [
...,
new UglifyjsPlugin(),
]
複製代碼
咱們但願打包後的文件能夠把es6語法轉爲es5,能夠經過babel-loader幫咱們實現
// src/a.js
console.log('this is a');
const fn = () => {
console.log('fn');
}
複製代碼
安裝babel依賴模塊
yarn add babel-loader @babel/core @babel/preset-env -D
複製代碼
{
test: /\.js|jsx$/, use:
{
loader: 'babel-loader', options: {
presets: ['@babel/preset-env']
}
}
},
複製代碼
如今寫es6的語法沒有問題了,可是咱們有可能用到es7的語法, 好比類的寫法,這時候咱們還須要藉助一個插件:@babel/plugin-proposal-class-properties 又好比裝飾器的寫法,咱們能夠藉助@babel/plugin-proposal-decorators來實現
{
test: /\.js|jsx$/, use:
{
loader: 'babel-loader', options: {
presets: ['@babel/preset-env'],
plugins: [
["@babel/plugin-proposal-decorators", { "legacy": true }], // 支持es7的裝飾器的寫法 要放在前面
'@babel/plugin-proposal-class-properties', // 支持es7的類的寫法
]
}
}
},
複製代碼
這裏須要注意的是@babel/plugin-proposal-decorators要放在@babel/plugin-proposal-class-properties前面。
babel只會幫咱們把es6新的語法轉成es5,可是對於新的API如:promise, generater 等咱們還須要藉助一個包 @babel-polyfill(可是比較大) 同時咱們能夠藉助一個插件--@babel/plugin-transform-runtime 作了必定優化,如代碼抽離
yarn add eslint eslint-loader
複製代碼
{
test: /\.js|jsx$/,
use: {
loader: 'eslint-loader',
options: {
enforce: 'pre', // pre post
}
}
},
複製代碼
接下來就可使用本身配置好的.eslintrc.json文件(放在根目錄下),固然咱們也能夠到eslint官網,手動進行配置,而後下載eslintrc.json,只要加個.就好了。
import $ from 'jquery';
console.log($)
console.log(window.$) // undefined
複製代碼
import $ from 'expose-loader?$!jquery';
console.log($)
console.log(window.$) // undefined
複製代碼
{
test: require.resolve('jquery'),
use: 'expose-loader?$'
},
// index.js
console.log(window.$)
複製代碼
let webpack = require('webpack');
new webpack.ProvidePlugin({ // 在每一個模塊中都注入$
$: 'jquery',
}),
// index.js
console.log($); // 均可以訪問
console.log(window.$)
複製代碼
externals: { // 外部引入,不須要打包
jquery: '$',
},
// index.js
import $ from 'jquery'; // 雖然引入可是不會再打包
console.log($);
複製代碼
咱們使用圖片的場景有兩種:
// index.js
let img = new Image();
img.src = require('./logo.png');
document.body.appendChild(img);
複製代碼
這時咱們須要藉助 file-loader 了
{
test: /\.png|jpg|gif|jpeg$/,
loader: 'file-loader',
options: {
}
},
複製代碼
// index.js
import logo from './logo.png'; // 返回一個新的文件 好處是能夠重命名圖片
let img = new Image();
img.src = logo;
document.body.appendChild(img);
// a.css
body{
color: yellow;
background: url('./logo.png') no-repeat;
}
複製代碼
ok,發現前兩種都沒有什麼問題,但是第三種直接寫在html中的卻不行
<body>
<img src='./logo.png' alt=""/>
<!-- 模版 -->
</body>
複製代碼
處理直接寫在html裏的圖片,還須要用到另外一個loader:
{
test: /\.html/,
use: 'html-withimg-loader'
},
複製代碼
從新啓動就行了。
若是想要作更多的限制呢,好比說對打包圖片大小的限制打包成base64以減小http請求(base64會比源文件大1/3左右),咱們可使用 url-loader
{
test: /\.png|jpg|gif|jpeg$/,
loader: 'url-loader',
options: {
limit: 4 * 1024, // 圖片大小限制值
outputPath: '/img/', // 輸出目錄
publicPath: 'http://58.com' // 添加打包後的圖片域名
}
},
複製代碼
基本配置以下:
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
home: './src/index.js',
other: './src/other.js',
},
output: {
filename: '[name].js', // name爲變量,根據entry的命名生成對應打包後的文件名稱
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new HtmlWebpackPlugin({ // 這裏須要new多個HtmlWebpackPlugin
template: './src/index.html',
filename: 'home.html',
chunks: ['home'] // html依賴,決定了打包後的哪些文件插入該模版中, 能夠寫多個,且有順序
}),
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'other.html',
chunks: ['other', 'home']
}),
],
}
複製代碼
// devtool: 'source-map', // 增長映射文件 會單獨生成一個sourcemap文件,出錯了會標示當前出錯的列和行 特色 大 全
devtool: 'eval-map',
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'home.html',
}),
],
複製代碼
output: {
filename: '[name].js', // name爲變量,根據entry的命名生成對應打包後的文件名稱
path: path.resolve(__dirname, 'dist'),
},
watch: true, // 實時編譯打包
watchOptions: { // 監控選項
poll: 1000, // 每秒訪問多少次
aggregateTimeout: 500, // 防抖
ignored: /node_modules/
},
複製代碼
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'home.html',
}),
new CleanWebpackPlugin('./dist'), // 傳入要刪除的目錄 也可傳數組
new CopyWebpackPlugin([{ from: './src/static', to: './dist' }]), //須要拷貝的目錄 必須是arr
new webpack.BannerPlugin('make 2019 by beth.miao'),
],
複製代碼
proxy: {
'/api': {
target: 'http://localhost:3001',
pathRewrite: { '/api': '' }
}
}
複製代碼
resolve: { // 解析第三方包 common
modules: [path.resolve('node_modules')],
// mainFields: ['style', 'main'],
// mainFiles: '',
alias: {
bootstrap: 'bootstrap/dist/css/bootstrap.css',
},
extensions: ['.js', '.css', '.json', 'vue'], // 引入路徑後綴名處理
},
複製代碼