一.项目简介
本项目运用vue作为前端框架,thinkJs作为后端框架,构建个人博客网站,页面分为博客展现和背景治理,重要目标是进修运用thinkJs。如今只完成了重要的博客增编削功用,发明webpack的设置遇到了一些坑,这里先记录下。项目目次构造以下:
个中system文件夹是前端vue项目标代码,博客展现页面与背景治理页面都在这里,打包成两个页面,详细webpack设置是本文重点。项目地点在这
二.搭建历程
装置nodejs后,起首装置thinkjs
npm install -g think-cli;
thinkjs new self_blog;
npm install;
npm start;
如许thinkJs项目开端搭建完成了,接下来建立vue项目。项目根目次下新建文件夹system。
npm install -g vue-cli
vue init webpack self_blog
cd self_blog
npm install
npm run dev
如许vue项目开端搭建终了,接下来说下这里vue的详细webpack设置。
三.webpack设置
项目前端页面分为博客的展现和背景治理,这里的思绪是将sytem的src下面放背景治理页面,在sytem下新建blog文件夹,放前台展现页面,打包时天生两个html,完成webpack打包多页面运用。目次以下:
1.webpack.base.conf.js的设置
运用vue-cli建立项目,npm run dev运转开辟环境,会运用webpack-dev-server作为前端效劳器,从而完成热加载。如许打包的文件只会在内存里,这里我的思绪是直接天生到thinkJs项目标view目次下,经由过程效劳端的路由返回给前端。如许只用启动后端的效劳就好了,由于文件已打包到效劳端,前端也不存在跨域接见后端的问题了。所以这里就不须要设置devServer了,而是转变html与js等静态资本的天生目次。起首看下webpack.base.conf.js的代码:
"use strict";
const path = require("path");
const utils = require("./utils");
const config = require("../config");
const vueLoaderConfig = require("./vue-loader.conf");
const webpack = require("webpack");
const baseFileName = require("../package.json").name;
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const cleanWebpackPlugin = require("clean-webpack-plugin");
const AssetsPlugin = require("assets-webpack-plugin");
function resolve(dir) {
return path.join(__dirname, "..", dir);
}
module.exports = {
context: path.resolve(__dirname, "../"),
entry: {
app: "./src/main.js",
blog: "./blog/index.js"
},
output: {
path: config.build.assetsRoot,
filename: "[name].js",
publicPath:
process.env.NODE_ENV === "production"
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: [".js", ".vue", ".json"],
alias: {
vue$: "vue/dist/vue.esm.js",
"@": resolve("src")
}
},
externals: {
vue: "Vue",
"vue-router": "VueRouter",
echarts: "echarts",
ElementUI: "element-ui"
},
module: {
rules: [
{
test: /\.vue$/,
loader: "vue-loader",
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: "babel-loader",
include: [
resolve("src"),
resolve("test"),
resolve("node_modules/webpack-dev-server/client")
]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: "url-loader",
exclude: [resolve("src/icons")],
options: {
limit: 10000,
name: utils.assetsPath(baseFileName + "/img/[name].[hash:7].[ext]")
}
},
{
test: /\.svg$/,
loader: "svg-sprite-loader",
include: [resolve("src")],
options: {
symbolId: "icon-[name]"
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: "url-loader",
options: {
limit: 10000,
name: utils.assetsPath(baseFileName + "/media/[name].[hash:7].[ext]")
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: "url-loader",
options: {
limit: 10000,
name: utils.assetsPath(baseFileName + "/fonts/[name].[hash:7].[ext]")
}
}
]
},
plugins: [
new AssetsPlugin({
filename: "build/webpack.assets.js",
processOutput: function(assets) {
return "window.WEBPACK_ASSETS=" + JSON.stringify(assets);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: "vendor",
minChunks: function(module) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(path.join(__dirname, "../node_modules")) === 0
);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: "manifest",
minChunks: Infinity
}),
new ExtractTextPlugin({
filename: utils.assetsPath(
baseFileName + "/css/[name].[contenthash].css"
),
allChunks: true
}),
// 编译前删除之前编译天生的静态资本
new cleanWebpackPlugin(["www/static/self_blog", "view/blog"], {
root: resolve("../")
})
],
node: {
setImmediate: false,
dgram: "empty",
fs: "empty",
net: "empty",
tls: "empty",
child_process: "empty"
}
};
起首须要改的是进口文件,由于是多页面运用,须要多个进口文件来保证打包成差别的chunk。我们晓得一般vue-cli建立的但页面运用,会打包成三个chunk,分别是vendor.js(第三方依靠),manifest.js(异步加载的完成),app.js(营业代码)。这里新增一个进口文件,打包时就会天生名为blog.js的chunk,含有前台展现页面的js营业代码。
这里新增运用的clean-webpack-plugin,是为了每次编译后,删除之前天生的js,css等静态资本,不然由于这些资本不重名,就会一向堆在你天生的目次下。
另外一些第三方依靠,vue,elementUI什么的,我运用了cdn引入,如许打包时这些依靠不会打进去,进而减小的vendor.js的体积。详细做法就是设置里的externals定义这些依靠,然后在天生html的模板里用script标签直接引入cdn里的js。
注重一下,假如你开辟时想用vue-devtool,须要引入vue.js,假如不必就引入vue.min.js。
2.webpack.dev.conf.js的设置
先看下代码:
"use strict";
const utils = require("./utils");
const webpack = require("webpack");
const config = require("../config");
const merge = require("webpack-merge");
const path = require("path");
const baseWebpackConfig = require("./webpack.base.conf");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin");
const portfinder = require("portfinder");
const HOST = process.env.HOST;
const PORT = process.env.PORT && Number(process.env.PORT);
const baseFileName = require("../package.json").name;
function resolve(dir) {
return path.join(__dirname, "..", dir);
}
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.dev.cssSourceMap,
extract: true,
usePostCSS: true
})
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
output: {
path: resolve(config.dev.assetsRoot),
filename: "static/" + baseFileName + "/js/[name]-[hash:5].js",
chunkFilename: "static/" + baseFileName + "/js/[name]-[id:5].js"
},
plugins: [
new webpack.DefinePlugin({
"process.env": require("../config/dev.env")
}),
// new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: resolve(`../view/blog/index_index.html`),
template: "./view/index.html",
title: "博客治理体系",
favicon: resolve("favicon.ico"),
inject: true,
chunks: ["manifest", "vendor", "app"]
}),
new HtmlWebpackPlugin({
filename: resolve(`../view/blog/blog_index.html`),
template: "./view/blog.html",
title: "博客展现",
inject: true,
chunks: ["manifest", "vendor", "blog"]
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, "../static"),
to: config.dev.assetsSubDirectory,
ignore: [".*"]
}
])
]
});
module.exports = devWebpackConfig;
这里我删掉了之前默许设置的devSever,以及module.exports直接导出devWebpackConfig。另外,由于打包天生目次的变化,我修改了output内里的path,filename,chunkFilename。使他们天生到self_blog根目次的www/static下面,这也是thinkJs静态资本的默许目次。须要注重下,filename指的是你的出口文件(app),以及经由过程codespliting天生的js(vendor,manifest)的文件名;chunkFilename定义的是一些懒加载组件打包后的js文件名。
下面须要增加的就是html-webpack-plugin,由于须要打包成两个html,所以运用两次这个插件。除了定义天生文件名(filename),html模板(template)等,还须要定义你这个html须要的chunk,这是跟单页面设置的一个区分。
除此之外,假如你想要开辟环境打包时就星散出css,那末在运用utils.styleLoaders时,将extract置为true。由于这里的要领推断是开辟环境才运用extract-text-plugin抽离css。
3.webpack.prod.conf.js的设置
prod的设置与dev差不多,天生文件目次也没变,只不过多了一些js,css紧缩插件。
"use strict";
const path = require("path");
const utils = require("./utils");
const webpack = require("webpack");
const config = require("../config");
const merge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.conf");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const OptimizeCSSPlugin = require("optimize-css-assets-webpack-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const baseFileName = require("../package.json").name;
const env = require("../config/prod.env");
function resolve(dir) {
return path.join(__dirname, "..", dir);
}
const webpackConfig = merge(baseWebpackConfig, {
entry: {
app: "./entry/entry-client-index",
blog: "./entry/entry-client-blog"
},
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: resolve(config.dev.assetsRoot),
filename: "static/" + baseFileName + "/js/[name]-[chunkhash:5].js",
chunkFilename: "static/" + baseFileName + "/js/[name]-[chunkhash:5].js"
},
plugins: [
new webpack.DefinePlugin({
"process.env": require("../config/prod.env"),
"process.env.VUE_ENV": '"client"'
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.LoaderOptionsPlugin({
minimize: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath(
baseFileName + "/css/[name].[contenthash].css"
),
allChunks: true
}),
new HtmlWebpackPlugin({
minify: {},
chunksSortMode: "dependency",
environment: process.env.NODE_ENV,
filename: resolve(`../view/blog/index_index.html`),
template: "./view/index.html",
title: "博客治理体系",
favicon: resolve("favicon.ico"),
inject: true,
chunks: ["manifest", "vendor", "app"]
}),
new HtmlWebpackPlugin({
filename: resolve(`../view/blog/blog_index.html`),
template: "./view/blog.html",
title: "博客展现",
favicon: resolve("favicon.ico"),
inject: true,
chunks: ["manifest", "vendor", "blog"]
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
]
});
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require("compression-webpack-plugin");
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: new RegExp(
"\\.(" + config.build.productionGzipExtensions.join("|") + ")$"
),
threshold: 10240,
minRatio: 0.8
})
);
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
}
module.exports = webpackConfig;
四.总结
详细能够看github上的代码
本次项目重要目标是演习thinkJs,这里先把前期webpack设置方面的东西简朴说下,下一篇将会细致讲下thinkJs的运用要领和特征。项目会继承更新,不少东西还没做完呢。