做爲一個複製粘貼工程師,一直以來都是(可能只有我這樣 o(╥﹏╥)o )css
vue create hello-world
npx create-react-app hello-world
複製代碼
相似這樣的腳手架命令一頓操做,什麼Babel啊、Postcss、各類Loader、Eslint啊Uglifyjs都一把梭好了,然鵝到底這些是怎麼配置的,不知足需求的時候怎麼辦呢? 這些腳手架都是基於Webpack(Webpack是什麼?點我)的,最近在寫原生JS項目,沒有了腳手架就沒有Babel、autoprefixer、Uglifyjs了,那誰給我轉代碼,誰給我加瀏覽器前綴、誰給我壓縮代碼啊!複製粘貼工程師的自我修養告訴我不能這樣,這些活仍是讓別人幹比較好ヽ(✿゚▽゚)ノhtml
因而就開始了新的複製之旅vue
先來複制一段,新建個項目,項目根目錄下npm init -y
,-y就是全yes了,至於yes了啥胸弟們能夠不-y試試 ︿( ̄︶ ̄)︿node
項目目錄下多了個package.json,裏面記錄了項目相關的信息。 react
基於Webpack咱們固然要安裝Webpack了webpack
npm i webpack webpack-cli -D
複製代碼
命令完成後,項目中多了一個 node_modules文件夾,該文件夾是用來存放項目中安裝的依賴包,之後項目依賴的包也都會在裏面。git
初始化項目目錄,新建src、dist、config以及index.html(html裏隨便寫點啥好比hello world等會打開了至少不是白的就行),還有src目錄下的入口文件index.js(空的便可)es6
初始化工做基本就完成了 webpack打包默認入口爲src/index.js, 默認打包模式爲 --mode development, 打包模式總共有兩種:github
如今能夠在package.json -> scripts 欄目 配置build的命令web
{
"name": "test-webpack-bundler",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --mode production"
},
下面太長省略了...
}
複製代碼
而後執行npm run build
webpack配置工程師警告(๑•̀ㅂ•́)و✧
先npm i webpack-dev-server html-webpack-plugin internal-ip -D
開發環境本地服務就靠webpack-dev-server了,生成html、自動插入js等就靠html-webpack-plugin了,局域網設備可經過IP訪問就靠internal-ip 在config目錄裏新建一個webpack.dev.js
又到了複製粘貼的時候啦
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const packageConfig = require("../package.json");
const internalIp = require('internal-ip') // 藉助這個實現可用局域網IP訪問
const devWebpackConfig = {
mode: "development",
devtool:'#source-map',
devServer: {
port: 9527, // 指定端口號; 默認 8080
hot: true, // 熱更新
host: internalIp.v4.sync(), // 可經過局域網IP訪問,也能夠經過 localhost 訪問
open: true, // 啓動本地服務後,自動打開頁面
overlay: true, // 編譯器錯誤或警告時, 在瀏覽器中顯示全屏覆蓋; 默認false
progress: true, // 是否將運行進度輸出到控制檯; 默認 false
contentBase: path.resolve(__dirname, "dist"), // 告訴服務器從哪裏提供內容。只有在你想要提供靜態文件時才須要
publicPath: "/",
// 精簡終端輸出
stats: {
modules: false,
children: false,
chunks: false,
chunkModules: false
}
},
entry: ["./src/index.js"],
plugins: [
new HtmlWebpackPlugin({
template: "index.html", // 指定模板html文件
title: packageConfig.name, // html的title的值,這裏我從package.json裏取了
inject: true, // 自動引入JS腳本的位置,默認值爲 true
})
]
};
module.exports = devWebpackConfig;
複製代碼
devtool詳情看這裏 如今在package.json -> scripts 中配置dev的命令
"dev": "webpack-dev-server --config config/webpack.dev.js --color --progress"
複製代碼
如今npm run dev
吧 胸弟們熟悉的不要不要的了吧,走你
沒問題咱們繼續,有問題···胸弟們百度一下吧
如今咱們就參考Vue Cli生成的項目整理目錄吧
webpack只認識js,圖標、字體、css等其餘的就須要各類loader拿給webpack,它才認識。
先搞定css吧,順便把sass和scss也搞了(less同理,找對應loader便可) 隨便寫幾句意思一下
index.html
<header class="flex-container header-wrapper">
<h1 class="title">test-webpack4-bundler</h1>
<div class="user-avatar-box">
<img class="adaptive-img" src="./src/assets/uncle.jpg" alt="" />
</div>
<ul>
<li class="list-item">1</li>
<li class="list-item">2</li>
<li class="list-item">3</li>
<li class="list-item">4</li>
<li class="list-item">5</li>
<li class="list-item">6</li>
</ul>
</header>
複製代碼
src/index.js
import './styles/index.scss' // global css
複製代碼
src/styles/index.scss
@import "./header.scss";
.flex-container {
display: flex;
justify-content: center;
align-items: center;
}
.adaptive-img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
}
複製代碼
src/styles/header.scss
.header-wrapper {
flex-direction: column;
.title {
color: rgb(65, 85, 28);
}
.user-avatar-box {
width: 120px;
height: 120px;
overflow: hidden;
border-radius: 50%;
}
}
複製代碼
複製粘貼
npm i css-loader style-loader sass-loader sass postcss-loader autoprefixer -D
複製代碼
裝一堆 看名字也知道大概是幹什麼的了吧 postcss-loader配合autoprefixer就能夠自動加-webkit這些前綴了
(固然PostCSS還能幹不少事,想要了解的話點我)
config/webpack.dev.js裏,和plugins同級配置loader
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
"style-loader",
"css-loader",
"postcss-loader",
{
loader: "sass-loader",
options: {
implementation: require("sass")
// 默認使用的node-sass,這樣配置就會使用dart-sass
}
}
// webpack的規定,多個loader要倒着寫,好比scss文件先給sass-loader解析成css再給css-loader,以此類推
]
}
]
}
複製代碼
項目根目錄下建立兩個文件用來配置postcss-loader和autoprefixer
.browserslistrc
> 1%
last 2 versions
not ie <= 9
複製代碼
postcss.config.js
module.exports = {
plugins: {
autoprefixer: {}
}
};
複製代碼
又能夠npm run dev
了 已經看到咱們想要的樣子而且已經自動加了針對不一樣內核的前綴
css部分已經結束了,如今咱們寫點牛逼的代碼吧
utils/index.js
export function $(selector) {
return document.querySelector(selector);
}
複製代碼
src/index.js
import "./styles/index.scss"; // global css
import { $ } from "./utils";
import { resolve } from "path";
window.onload = () => {
const showText = "守護姨父的微笑";
setTimeout(() => {
}, 1000);
const changeTitle = () => {
let myPromise = new Promise((resolve, reject) => {
resolve();
});
return myPromise;
};
changeTitle().then(()=>{
$(".title").innerHTML = `咱們要${showText}`;
const lists = [...document.querySelectorAll(".list-item")];
lists.forEach(element => {
console.log(element);
});
let [a, b, c] = ["索尼好!退果報平安", 2, 3];
console.log(a);
$(".title").innerHTML = `咱們要${showText}${a}`;
})
};
複製代碼
好了咱們寫了箭頭函數、模板字符串、const聲明、Promise都是es6的語法,某些不現代的瀏覽器不支持,因此咱們須要Babel老弟幫幫咱們
複製粘貼
npm i babel-loader @babel/core @babel/preset-env @babel/runtime @babel/plugin-transform-runtime @babel/plugin-syntax-dynamic-import -D
複製代碼
src/index.js 頭部引入墊片
import "@babel/polyfill";
複製代碼
項目根目錄下新建.babelrc
{
"presets": ["@babel/preset-env"],
"plugins": [
"@babel/plugin-transform-runtime"
]
}
複製代碼
config/webpack.dev.js 裏module>rules下增長一個loader
{
test: /\.js$/,
use: ["babel-loader"],
exclude: /node_modules/
},
複製代碼
config/webpack.dev.js entry加入 @babel/polyfill
entry: ["@babel/polyfill","./src/index.js"]
複製代碼
package.json -> scripts build
"build": "webpack --config config/webpack.dev.js --mode production --color --progress"
複製代碼
npm run build
走一波
(babel-polyfill和babel-runtime的關係和區別大概能夠看這裏)
好像大概是弄完了?等等,打包出來的html文件圖片引用路徑好像不對,沒hash值迭代了緩存不得搞死咱們啊,那麼下一輪複製粘貼又要開始了。
開發環境大概就這麼樣了吧,針對生產環境咱們須要再搞點東西了 先複製一份webpack.dev.js,叫webpack.prod.js,做爲生產環境的webpack配置
裝,分別是解決js和html裏的文件路徑問題
npm i url-loader file-loader html-withimg-loader -D
複製代碼
而後刪除開發服務器,
config/webpack.prod.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const packageConfig = require("../package.json");
const prodWebpackConfig = {
mode: "production",
devtool: false,
entry: ["@babel/polyfill", "./src/index.js"],
output: {
path: path.resolve(__dirname, "../dist"),
filename: path.posix.join("static", "js/[name].[chunkhash].js"),
chunkFilename: path.posix.join("static", "js/[id].[chunkhash].js")
},
module: {
rules: [
{
test: /\.js$/,
use: ["babel-loader"],
exclude: /node_modules/
},
{
test: /\.(sa|sc|c)ss$/,
use: [
"style-loader",
"css-loader",
"postcss-loader",
{
loader: "sass-loader",
options: {
implementation: require("sass")
// 默認使用的node-sass,這樣配置就會使用dart-sass
}
}
// webpack的規定,多個loader要倒着寫,好比scss文件先給sass-loader解析成css再給css-loader,以此類推
]
},
{
test: /\.(htm|html)$/,
loader: "html-withimg-loader"
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: "url-loader",
options: {
limit: 10000,
name: path.posix.join("static", "img/[name].[hash:7].[ext]")
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: "url-loader",
options: {
limit: 10000,
name: path.posix.join("static", "fonts/[name].[hash:7].[ext]")
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "index.html", // 指定模板html文件
title: packageConfig.name, // html的title的值,這裏我從package.json裏取了
inject: true, // 自動引入JS腳本的位置,默認值爲 true
minify: {
minifycss: true, // 壓縮css
minifyJS: true, // 壓縮JS
removeComments: true, // 去掉註釋
collapseWhitespace: true, // 去掉空行
removeRedundantAttributes: true, // 去掉多餘的屬性
removeAttributeQuotes:true, // 刪除不須要引號的屬性值
removeEmptyAttributes: true // 去掉空屬性
}
})
]
};
module.exports = prodWebpackConfig;
複製代碼
package.json -> scripts build 該用生產環境的配置build了
"build": "webpack --config config/webpack.prod.js --mode production --color --progress"
複製代碼
npm run build
走一波
能夠看到,html壓縮過了,img路徑也正確了,同時目錄結構也整齊多了,文件也帶了hash值
大致上完成了,後續還有一些優化,好比用指定的插件去壓縮JS,CSS抽離成單個文件並優化,將根目錄下的static下靜態資源copy到打包目錄下等,單獨抽離第三方庫等,就不一一說了,主要寫這玩意太累了。。。大佬們好牛逼。。。。真的
若是有哪裏有問題歡迎大佬們告訴我!感恩!
附上這個項目的地址 裏面包含了比較完整的配置,至少個人項目裏大概就是這樣了。