摘要:豹哥對于剛開始小白的自己雖然現(xiàn)在也白知無不談,而且回復(fù)超快超認(rèn)真。這里真的很感謝豹哥。是項目啟動時的一些文件,如的配置文件開發(fā)環(huán)境服務(wù)配置文件一些簡單工具函數(shù)等等。是關(guān)于整個項目的環(huán)境配置包括開發(fā)與生產(chǎn)。
前言
作者去年就開始使用webpack, 最早的接觸就來自于vue-cli。那個時候工作重點主要也是 vue 的使用,對webpack的配置是知之甚少,期間有問題也是詢問大牛 @呂大豹。順便說一句,對于前端知識體系迷茫的童鞋可以關(guān)注豹哥的微信公眾號,《大豹雜說》。豹哥對于剛開始小白的自己(雖然現(xiàn)在也白)知無不談,而且回復(fù)超快超認(rèn)真。這里真的很感謝豹哥。前段時間工作不忙,自己就啃了啃webpack的官方文檔,畢竟知識還是在自己腦袋里踏實。然后根據(jù)vue-cli的配置文件豐富了一點新的東西,發(fā)布出來大家共享,同時自己也有點疑問,也歡迎各位評論給小子指正。
webpack的學(xué)習(xí)在前端領(lǐng)域我們總要面對各種的新框架新工具,那么怎么有效快速的學(xué)習(xí)掌握一門技能呢?作者的方法是實踐是最好的老師,建議新東西了解一些核心的API啊功能啊立刻就上手使用,這個過程肯定會出現(xiàn)各種問題,在尋求解決問題的途徑中逐漸也就加深了理解,帶著問題學(xué)習(xí)總歸會事半功倍。拿webpack來講,了解他的一些核心概念,配置文件的入口輸出解析loader,plugin等等就可以簡單使用了。這里建議一點,學(xué)習(xí)新知識的時候建議大家最終還是從官網(wǎng)啊官方文檔中學(xué)習(xí),英文真的不是事,得試試才知道自己能看懂的。看博客主要都是別人消化之后的東西,再有基礎(chǔ)之上再看這些文章當(dāng)然能起到查漏補缺的功效,但是一開始就看,就很容易受到作者思路局限的影響。
當(dāng)然這些都是自己的建議啊。所以本篇文章面對的是對webpack有一些簡單使用的朋友,大家分享經(jīng)驗而已,如果對webpack還沒開始使用的朋友,建議還是先了解一下webpack的核心知識。官網(wǎng)有中文版,翻譯的也很好。
webpack環(huán)境的區(qū)別webpack本質(zhì)就是一個打包工具,是一種模塊化開發(fā)的實現(xiàn),它與gulp與grunt這一類的自動化構(gòu)建工具不同,構(gòu)建工具是優(yōu)化我們自己的工作流程,將眾多的手工方式改為自動化,比如壓縮js、css,編譯scss,less。當(dāng)然webpack的loader與plugin也可以完成這些工作,工具使用看個人公司需求。webpack的主要工作是將我們我編寫的模塊化的文件打包編譯為瀏覽器所能辨識的方式。
直白來講,開發(fā)環(huán)境,就是你的代碼在本地服務(wù)器上在測試、更改、運行,生產(chǎn)環(huán)境你的代碼就是已經(jīng)開始在真實服務(wù)器中使用。webpack 可以適用于開發(fā)環(huán)境主要是運用了node.js 搭建一個本地服務(wù)。記得去年我剛開始想需要一個本地服務(wù)的時候開始是使用Hbuilder,后來多帶帶用了一個小工具名字好像叫webservice。
前面提到了nodejs,node.js是一個javascript運行的平臺而不是什么js的框架,它實現(xiàn)的是js不僅可以開發(fā)客戶端瀏覽器也可以開發(fā)服務(wù)端。現(xiàn)在的前端項目中都會發(fā)現(xiàn)一個package.json
</>復(fù)制代碼
{
"name": "webpack_environment",
"version": "1.0.0",
"description": "A webpack environment test",
"author": "abzerolee",
"scripts": {
"dev": "node build/dev-server.js",
"build": "node build/build.js"
},
"dependencies": {
"nimble": "^0.0.2"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-loader": "^7.1.1",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"clean-webpack-plugin": "^0.1.16",
"connect-history-api-fallback": "^1.3.0",
"css-loader": "^0.28.0",
"eventsource-polyfill": "^0.9.6",
"express": "^4.14.1",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^0.11.1",
"glob": "^7.1.2",
"html-webpack-plugin": "^2.28.0",
"http-proxy-middleware": "^0.17.3",
"less": "^2.7.2",
"less-loader": "^4.0.5",
"mockjs": "^1.0.1-beta3",
"opn": "^5.1.0",
"ora": "^1.3.0",
"postcss-loader": "^2.0.6",
"rimraf": "^2.6.1",
"style-loader": "^0.18.2",
"url-loader": "^0.5.8",
"webpack": "^3.1.0",
"webpack-dev-middleware": "^1.10.0",
"webpack-hot-middleware": "^2.18.0",
"webpack-merge": "^4.1.0"
}
}
這個文件可以用npm 模塊管理器生成的,它描述了一個項目的各種信息,注意到script這個屬性他對應(yīng)的dev build就是開發(fā)環(huán)境與生產(chǎn)環(huán)境了,我們運行命令的話是用 ‘npm run dev’或‘npm run build’其實執(zhí)行的就是對應(yīng)的node編譯。可以發(fā)現(xiàn)這個配置文件告訴我們開發(fā)環(huán)境與生產(chǎn)環(huán)境的入口文件/build/dev-server.js,/build/build.js。剩下的dependencies / devDependencies則代表兩種環(huán)境對應(yīng)的依賴需要。
目錄結(jié)構(gòu)先介紹/node_modules 我們使用npm install 就是通過package.json中的依賴配置對應(yīng)安裝你需要的一些庫,可以發(fā)先我在生產(chǎn)環(huán)境需要的是nimble。那么這些庫存放的地方就是在/node_moudles中。當(dāng)然你也可以用曾經(jīng)古老的方法新建一個/lib 然后去官網(wǎng)下載對應(yīng)js文件,再放入/lib。但是這樣對于整個項目的管理并不十分友好,我們查看項目的依賴庫只需要查看package.json就夠了 而不是去html頁面一個個找
/config 是關(guān)于整個項目的環(huán)境配置包括開發(fā)與生產(chǎn)。我們在node引入模塊的時候可以直接引入目錄,
</>復(fù)制代碼
require("./config");
他默認(rèn)查找的就是該目錄下的index.js文件。當(dāng)然也可以不叫index.js這個需要一個/config目錄下再去寫一個package.json指定文件。
/dist與/src /dist目錄下是將/src 目錄下的源碼編譯之后生成的文件。一般項目部署就直接可以將/dist目錄下的文件放在網(wǎng)站的根目錄。/dist就對應(yīng)生產(chǎn)環(huán)境的文件,/src對應(yīng)開發(fā)環(huán)境的文件。
/mock 是前臺開發(fā)的模擬數(shù)據(jù)接口的文件,里面就是一些后臺接口的模擬數(shù)據(jù)
</>復(fù)制代碼
var Mock = require("mockjs");
var User = {
login: {
code: 0,
info: null,
msg: "登錄成功!"
},
getVerifyCode: {
code: 0,
info: Mock.mock("@string("lower", 4)"),
msg: "操作成功"
}
};
module.exports = User;
這里使用了mock.js 來生成模擬數(shù)據(jù),用CommonJS規(guī)范中module.exports來暴露出數(shù)據(jù)。對于AMD,CMD,CommonJS這幾種模塊規(guī)范,大家還是應(yīng)該有適當(dāng)?shù)睦斫猓瑸槭裁匆心K,模塊的工作方式有什么。當(dāng)然這是一種規(guī)避跨域問題的模擬測試,項目中也通過http-proxy-middleware的方式解決跨域問題。但是如果后臺的進(jìn)度慢于前臺的情況下,這種mock也是一種良好的開發(fā)方式。
開發(fā)環(huán)境 dev-server.js作者最開始學(xué)習(xí)webpack的時候,也是從把a.js與b.js引入main.js最后打包生成bundle.js開始的。那個時候?qū)ode.js也是一知半解,當(dāng)然現(xiàn)在了解的更多了,并不代表精通。總會好奇一個點就是 剛開始編譯的時候是使用
webpack -config webpack.conf.js
后面怎么開始用node編譯了。其實這是webpack提供了一個Node.js API,可以直接在Node.js運行時使用。這也就是為什么入口文件從webpack.conf.js變成了dev-server.js|build.js的原因。使用node編譯的好處是可以更好的利用一下node的特性 讀取文件,模擬API接口等等。
</>復(fù)制代碼
var config = require("../config");
if(!process.env.ENV) {
process.env.ENV = config.dev.ENV;
}
var utils = require("./utils");
var opn = require("opn");
var path = require("path");
var fs = require("fs");
var express = require("express");
var webpack = require("webpack");
var proxyMiddleware = require("http-proxy-middleware");
var webpackConfig = require("./webpack.dev.conf");
var port = process.env.PORT || config.dev.port;
var autoOpenBrowser = config.dev.autoOpenBrowser;
var proxyTable = config.dev.proxyTable;
var app = express()
var compiler = webpack(webpackConfig);
var apiRouter = express.Router();
var apis = fs.readdirSync(utils.resolve("/mock"));
var apiClass = apis.map(it => it.replace(/.js$/, ""));
apiRouter.route("/:apiClass/:apiName").all(function(req, res) {
var params = req.params;
var apiIndex = apiClass.indexOf(params.apiClass)
var err = {code: 99,info: null, msg: "no such api"}
if(apis.length < 1 || apiIndex === -1)
return res.json(err);
var klass = require("../mock/"+ apis[apiIndex]);
if(klass[params.apiName]){
res.json(klass[params.apiName]);
}else{
res.json(err);
}
})
app.use("/api", apiRouter);
var devMiddleware = require("webpack-dev-middleware")(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true
});
var hotMiddleware = require("webpack-hot-middleware")(compiler, {
log: () => {},
heartbeat: 2000
})
compiler.plugin("compilation", function (compilation) {
compilation.plugin("html-webpack-plugin-after-emit", function (data, cb) {
hotMiddleware.publish({ action: "reload" })
cb()
})
})
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === "string") {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
});
// app.use(require("connect-history-api-fallback")())
app.use(devMiddleware)
app.use(hotMiddleware)
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static("./static"));
var uri = "http://localhost:"+ port;
var _resolve;
var readyPromise = new Promise(resolve => {
_resolve = resolve
})
console.log("> Starting Server...");
devMiddleware.waitUntilValid(() => {
console.log("> Listening at " + uri + "
")
// when env is testing, don"t need open it
if (autoOpenBrowser && process.env.ENV !== "testing") {
opn(uri)
}
_resolve()
})
var server = app.listen(port);
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
}
上面的代碼用過vue-cli的朋友應(yīng)該很熟悉。對于vue-cli的介紹大家可以自己去官網(wǎng)查看。這里推薦一個對配置文件逐句注釋的文章,細(xì)微之處還是有差異的,但是大體不離。
我們盡量用直白的語言來分析一下這個文件,
程序開始運行,引入環(huán)境的配置文件/config 這里前文提到為什么可以省略index.js。然后判斷process.env表示的用戶環(huán)境變量 ENV 為何種環(huán)境,官網(wǎng)翻譯進(jìn)程對象process是一個全局的,它提供有關(guān)當(dāng)前Node.js進(jìn)程的信息和控制。這個環(huán)境變量我們可以在命令行中啟動程序時輸入,當(dāng)node無法判斷環(huán)境時我們手動的設(shè)置為開發(fā)環(huán)境的變量,在/config/index.js config.dev.ENV <=> "dev"。然后引入我們需要的庫和文件,比如工具函數(shù)庫utils 自啟動瀏覽器opn(服務(wù)啟動后自動打開瀏覽器) 文件系統(tǒng)fs nodejs框架express(用來啟動本地服務(wù)器,部署靜態(tài)服務(wù),模擬路由接口)。
引入庫之后便是定義我們的整個項目服務(wù)app,通過webpack的nodeAPI編譯開發(fā)環(huán)境的配置文件,定義webpack提供的服務(wù)的中間件webpack-dev-middleware,將編譯內(nèi)容寫入內(nèi)存中,啟用熱加載的中間件,html模板template更新則強制刷新頁面,以及配置跨域代理請求的中間件。中間件的概念其實就是工作流的思想,記得有一個例子很直白
可樂的生成:水 -> 凈化 -> 調(diào)配 -> 裝瓶 -> 質(zhì)檢 -> 飲用可樂,水到可樂,每一個中間過程都認(rèn)為是一個中間件
通過express.Router()來定義接口,所有本地請求的/api開頭的url都解析之后的/api/:apiClass/:apiName,apiName對應(yīng)/mock文件下的js文件名,apiName對應(yīng)js文件暴露出的對象的屬性也就是數(shù)據(jù)。。
這里因為配置了mock的原因我就去除了connect-history-api-fallback,它的作用因為找不到接口的話指定一個頁面重定向,如果接口API找不到它就會默認(rèn)定向到index.html。接下來是拼接/static文件路徑,我的靜態(tài)資源都是放在assets目錄下就就刪除了該文件夾。(對這點我也存有疑問就是vue-cli的這個/static文件夾到底是指哪些靜態(tài)資源?)。之后是服務(wù)啟動,監(jiān)聽端口打開瀏覽器。
到這里,我們就可以通過對src的源碼進(jìn)行修改開發(fā)了。
生產(chǎn)環(huán)境 build.js</>復(fù)制代碼
process.env.ENV = "prod";
var ora = require("ora");
var path = require("path")
var chalk = require("chalk")
var webpack = require("webpack")
var config = require("../config")
var webpackConfig = require("./webpack.prod.conf")
var spinner = ora("building for production...");
spinner.start()
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: true,
chunkModules: false
}) + "
")
console.log(chalk.cyan(" Build complete.
"))
console.log(chalk.yellow(
" Tip: built files are meant to be served over an HTTP server.
" +
" Opening index.html over file:// won"t work.
"
))
})
編譯打包功能就不需要配置服務(wù)了,當(dāng)然打包的時候需要一下提示,進(jìn)度,就需要ora chalk這些模塊了。打包這里和vue-cli不太一樣得是我沒有使用rmrf 而是用了一個插件CleanWebpackPlugin來清空/dist目錄下的文件。當(dāng)然也可以只清空某個文件而不是整個目錄。
配置文件 /config/index.js && /build/utils.js/config/index.js主要暴露了兩個對象一個屬性
</>復(fù)制代碼
var path = require("path");
module.exports = {
// 項目根目錄
_root_: path.resolve(__dirname, "../"),
// 生產(chǎn)環(huán)境設(shè)置
build: {
ENV: "prod",
index: path.resolve(__dirname, "../dist/index.html"), // 編譯完成首頁
assestsRoot: path.resolve(__dirname, "../dist"), // 靜態(tài)根目錄
assetsSubDirectory: "static",
assetsPublicPath: "",
prodSourceMap: false,
productionGzip: false,
productionGzipExtensions: ["js", "css"]
},
// 開發(fā)環(huán)境配置
dev: {
ENV: "dev",
port: "3000",
autoOpenBrowser: false,
assetsSubDirectory: "static",
assetsPublicPath: "/",
cssSourceMap: false,
proxyTable: {
// "/api": {
// target: "http://localhost:3100",
// changeOrigin: true
// }
}
}
}
這里注意的一個點就是build.assetsPublicPath <=> 編譯發(fā)布的根目錄,可配置為資源服務(wù)器域名或 CDN 域名,那么很多朋友vue編譯完本地File://打不開就是因為這里配置的是"/"指的是服務(wù)器的根目錄,部署到服務(wù)器上是沒有問題的,如果你要本地打開,設(shè)為空字符串即可。
第二個需要注意的就是dev.proxyTable的接口屬性,如我的配置其實就是跨域請求"http://localhost:3100/api"注意接口名的對應(yīng)。
utils是在編寫配置文件時你需要的一些函數(shù),比如vue-cli中關(guān)于樣式的loader都是在這里配置的
</>復(fù)制代碼
var path = require("path");
var config = require("../config");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var glob = require("glob");
exports.assetsPath = function(_path) {
var assetsSubDirectory = process.env.ENV === "prod"
? config.build.assetsSubDirectory
: config.build.assetsSubDirectory;
return path.posix.join(assetsSubDirectory, _path)
}
exports.resolve = function(dir) {
return path.join(__dirname, "..", dir);
}
exports.cssLoaders = function(options) {
var cssLoader = {
loader: "css-loader",
options: {
minmize: process.env.ENV === "prod",
sourceMap: options.sourceMap
}
}
function generLoaders(loader, loaderOptions) {
var loaders = [cssLoader, ];
if(loader) {
loaders.push({
loader: loader +"-loader",
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
if(options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: "style-loader",
})
}else {
return ["style-loader"].concat(loaders)
}
}
return {
css: generLoaders(),
postcss: generLoaders(),
less: generLoaders("less"),
sass: generLoaders("sass", {indentedSyntax: true}),
scss: generLoaders("sass")
}
}
exports.styleLoader = function(option) {
var output = [];
var loaders = exports.cssLoaders(option);
for(var extension in loaders){
output.push({
test: new RegExp("."+ extension +"$"),
use: loaders[extension]
})
}
return output
}
exports.getEntries = function(_path) {
var entries = {};
glob.sync(_path).forEach(function(entry) {
var basename = path.basename(entry, path.extname(entry));
var pathname = entry.split("/").splice(-3).splice(0, 1) +"/"+ basename;
entries[basename] = entry;
});
return entries;
}
assetsPath(_path)是返回靜態(tài)資源_path的全路徑,
resolve(dir)是返回dir的絕對路徑,為什么會多帶帶寫resolve主要是webpack的配置文件不在項目根目錄而是在/build下。
getEntries(_path) 是通過glob(路徑模式匹配模塊)匹配多頁面入口文件的函數(shù),最終返回一個入口對象,在這里網(wǎng)上很多其他得例子都是
</>復(fù)制代碼
{
"module/index": ...
"module/user": ...
}
這導(dǎo)致開發(fā)環(huán)境下需要在url去添加http://localhost:3000/module/...才能查看文件,生產(chǎn)環(huán)境編譯之后的文件也是在/dist/module/index.html 這里直接將basename 作為屬性名則會解決。
styleLoader() 返回一個webpack配置文件中moudle.rules對應(yīng)的數(shù)組,內(nèi)部調(diào)用cssLoader(來生成對應(yīng)的sass、less加載編譯) 這里不太明白的朋友建議可以在vscode下斷點調(diào)試一下,看他每次生成對象對應(yīng)的一些配置。
webpack.*.conf.jswebpack的配置文件各種各樣,這是因為他高度自定義決定的,你可以配置任何你想要的loader plugin來完成你的工作。像vue-cli便是定義了一個基礎(chǔ)的base配置,之后區(qū)分開發(fā)與生產(chǎn)需要的不同插件,都是代碼復(fù)用。base.conf中應(yīng)該注意的是多入口與單入口的配置
</>復(fù)制代碼
...
var entries = utils.getEntries("./src/modules/**/*.js");
module.exports = {
// entry: {
// app: utils.resolve("/src/main.js"),
// },
entry: entries,
output: {
path: config.build.assestsRoot,
filename: "[name].js",
publicPath: process.env.ENV === "prod" ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
},
...
</>復(fù)制代碼
module.exports = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoader({
sourceMap: config.dev.cssSourceMap
})
},
plugins: [
new webpack.DefinePlugin({
"process.env": config.dev.ENV,
dev_port: ""http://localhost:3000/api""
}),
new webpack.HotModuleReplacementPlugin(),
// spa 則應(yīng)用如下配置
// new HtmlWebpackPlugin({
// title: "Single-Page"+pathname,
// filename: "index.html",
// template: utils.resolve("/src/index.html"),
// inject: true
// })
]
})
// 多頁面應(yīng)用配置 根據(jù)modules 動態(tài)生成html
var pages = utils.getEntries("./src/modules/**/*.html");
for(var pathname in pages){
var conf = {
filename: pathname +".html",
template: pages[pathname],
chunks: [pathname],
inject: true
}
module.exports.plugins.push(new HtmlWebpackPlugin(conf))
}
該配置只使用了三個插件 DefinePlugin這個插件可以用來定義全局變量,在編譯時將你的引用的dev_port 轉(zhuǎn)換為 "http://locahost:3000/api" 要注意的是他轉(zhuǎn)化的是值,比如 dev_port <=> "b" 那么你在編寫代碼時 引用了dev_port實際上他是將變量名替換為b而不是"b"字符串,可以看如下報錯,所以要使用字符串時需要外層包裹單引號。
</>復(fù)制代碼
// dev.conf
...
new webpack.DefinePlugin({
"process.env": config.dev.ENV,
dev_port: "b"
}),
...
// /src/modules/index.js
...
console.log(dev_port);
...
HotModuleReplacementPlugint插件在頁面進(jìn)行變更的時候只會重繪對應(yīng)的頁面模塊,不會重繪整個html文件。HtmlWebpackPlugin有幾個頁面則對應(yīng)生成幾個配置。
與dev.conf類似的有,
DefinePlugin 但是這個時候要把dev_port切換后臺接口所在服務(wù)器的域名。這樣不用每次編譯前再去修改 當(dāng)然叫host可能更準(zhǔn)確(忽略我的瞎起名字)。HtmlWebpackPlugin就是一些生成html文件是否壓縮是否去除屬性引用的配置。
不同之處有配置了CommonsChunkPlugin提取公共模塊,(要注意minChunks最少引用次數(shù)的配置),ExtractTextPlugin提取CSS文件 而不是style標(biāo)簽插入html。
結(jié)語啃文檔啃了一個星期多,邊啃邊練一個星期,構(gòu)思寫作三天,起碼現(xiàn)在對weback的配置再恐懼了,文章有點過長能看到這的朋友首先謝謝你的閱讀,源碼在github 這個環(huán)境也是當(dāng)時用來打包一個以前用jquery的項目的所以沒有配框架vue react之類的。過段時間啃完了create-react-app 的實現(xiàn)應(yīng)該還會出一期關(guān)于 webpack 原理的學(xué)習(xí)筆記。還希望繼續(xù)關(guān)注。文中如有一些問題也希望大家及時指正。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/84649.html
摘要:開發(fā)環(huán)境和生產(chǎn)環(huán)境都擁有的配置,但在細(xì)節(jié)上有所不同,比如說,又比如說中的和參數(shù)。更重要的是,實際上開發(fā)環(huán)境和生產(chǎn)環(huán)境的配置文件的絕大部分都是一致的,對于這一致的部分來說,我們堅決要消除冗余,否則后續(xù)維護(hù)起來不僅麻煩,而且還容易出錯。 本文首發(fā)于Array_Huang的技術(shù)博客——實用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/11900...
摘要:它允許在運行時更新各種模塊,而無需進(jìn)行完全刷新。構(gòu)建生產(chǎn)環(huán)境開發(fā)環(huán)境和生產(chǎn)環(huán)境的構(gòu)建目標(biāo)差異很大。在開發(fā)環(huán)境中,我們需要具有強大的具有實時重新加載或熱模塊替換能力的和。 1. 構(gòu)建開發(fā)環(huán)境 如果你一直跟隨我前面的博文,那么你對webpack的基礎(chǔ)知識已經(jīng)有比較深刻的理解了。之前,我們一直執(zhí)行著: npm run build 來打包編譯輸出我們的代碼,本文我們來看看如何構(gòu)建一個開發(fā)環(huán)境,...
摘要:時至今日,已經(jīng)成為前端工程必備的基礎(chǔ)工具之一,不僅被廣泛用于前端工程發(fā)布前的打包,還在開發(fā)中擔(dān)當(dāng)本地前端資源服務(wù)器模塊熱更新等角色,結(jié)合等代碼檢查工具,還可以實現(xiàn)在對源代碼的嚴(yán)格校驗檢查。時至今日,Webpack 已經(jīng)成為前端工程必備的基礎(chǔ)工具之一,不僅被廣泛用于前端工程發(fā)布前的打包,還在開發(fā)中擔(dān)當(dāng)本地前端資源服務(wù)器(assets server)、模塊熱更新(hot module repla...
摘要:同時它還提供了自動刷新熱更新等功能,使開發(fā)變得非常方便。的到來減少了很多的配置,它內(nèi)置了很多的功能。 上一篇文章里詳細(xì)介紹了一下插件的用法,這一篇文章接著豐富module.exports里的屬性。如今的前端發(fā)展已經(jīng)非常迅速了,伴隨而來的是開發(fā)模式的轉(zhuǎn)變。現(xiàn)在已經(jīng)不再是寫個靜態(tài)頁面并放在瀏覽器里打開預(yù)覽一下了。在實際的開發(fā)中會經(jīng)常需要使用http服務(wù)器,比如之前的ajax,想要看到效果就...
相信vue使用者對vue-cli都不會陌生,甚至可以說,很熟悉了,但對其webpack的配置可能知之甚少吧。 過完年回來后,我接手了公司的新項目。新項目是一個spa。很自然,我就想到了vue-cli腳手架了,當(dāng)時研究一下它的webpack配置。于是,就有了其他的內(nèi)容。 今天這篇文章,是在原來的基礎(chǔ)上,增加了一些新版本的內(nèi)容,但實質(zhì)上變化不大。 說明 此倉庫為vue-cli webpack的配置分析...
閱讀 2852·2023-04-25 17:59
閱讀 683·2023-04-25 15:05
閱讀 673·2021-11-25 09:43
閱讀 3035·2021-10-12 10:13
閱讀 3537·2021-09-27 13:59
閱讀 3584·2021-09-23 11:21
閱讀 3880·2021-09-08 09:35
閱讀 569·2019-08-29 17:12
极致性价比!云服务器续费无忧!
Tesla A100/A800、Tesla V100S等多种GPU云主机特惠2折起,不限台数,续费同价。
NVIDIA RTX 40系,高性价比推理显卡,满足AI应用场景需要。
乌兰察布+上海青浦,满足东推西训AI场景需要