Nifty是一个基于Bootstrap的后台管理模版,不过需要付费购买,如果想用免费开源的可以考虑AdminLTE。
1.初始化,安装依赖
# 初始化项目
mkdir webpack-vue-nifty && cd webpack-vue-nifty && npm init -y
# 基础依赖
npm install --save-dev webpack \
webpack-cli \
style-loader \
css-loader \
file-loader \
url-loader \
html-loader \
html-webpack-plugin \
mini-css-extract-plugin
# 运行时依赖
npm install --save vue jquery [email protected] vue-router
# 打包构建时时依赖
npm install --save-dev vue-loader \
vue-style-loader \
vue-template-compiler \
vue-hot-reload-api \
babel \
[email protected] \
babel-core \
babel-plugin-transform-runtime \
babel-plugin-syntax-dynamic-import \
babel-preset-es2015 \
babel-runtime
# 开发调试
npm i --save-dev webpack-dev-server
2.补充npm脚本
package.json
{
"name": "webpack-vue-nifty",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"dev": "webpack-dev-server --inline --progress --compress --hot --open --history-api-fallback --config webpack.config.js --host 127.0.0.1 --port 8888"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel": "^6.23.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-runtime": "^6.26.0",
"css-loader": "^1.0.0",
"file-loader": "^2.0.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.4.3",
"style-loader": "^0.23.1",
"url-loader": "^1.1.1",
"vue-hot-reload-api": "^2.3.1",
"vue-loader": "^15.4.2",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.5.17",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.9"
},
"dependencies": {
"bootstrap": "^3.3.7",
"jquery": "^3.3.1",
"vue": "^2.5.17",
"vue-router": "^3.0.1"
}
}
3.完善webpack配置
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
mode: 'production',
entry: {
index: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[hash:8].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015'],
plugins: ['transform-runtime', 'syntax-dynamic-import']
}
}
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../' // 特别重要,否则css文件打包后其中引用的图片文件不正确
}
},
"css-loader"
]
},
{
test: /\.html$/,
use: {
loader: 'html-loader'
}
},
{
test: /\.(png|jpg|gif|jpeg|svg|eot|woff|woff2|ttf)$/,
use:[
{
loader: "url-loader",
options: {
name: "img/[name].[hash:5].[ext]",
limit: 1024, // size <= 1kib
// outputPath: "img",
publicPath: "../"
}
}
]
},
{
test: /\.vue$/,
use: 'vue-loader'
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].[hash:8].css",
}),
new HtmlWebpackPlugin(
{
template: './src/index.html',
filename:'./index.html',
hash: false,
chunks: ['index']
}
),
new VueLoaderPlugin(),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Vue: ['vue/dist/vue.esm.js', 'default'],
VueRouter: ['vue-router/dist/vue-router.esm.js', 'default']
})
],
devServer: {
contentBase: path.resolve(__dirname, "../dist/"),
index:'./index.html'
}
};
4.完善入口文件,配置路由
index.js
import App from './app.vue'
Vue.use(VueRouter);
const Container = () => import('./pages/container.vue');
const Home = () => import('./pages/home.vue');
const Setting = () => import('./pages/setting.vue');
const routes = [
{
path: '/',
component: Container,
children: [
{ path: '/home', component: Home },
{ path: '/setting', component: Setting }
]
},
{ path: '/setting', component: Setting }
];
const router = new VueRouter({
mode: 'history',
routes: routes
});
new Vue({
el: '#app',
router: router,
components: { App }
});
index.html
Title
app.vue
5.引入Nifty
复制nifty中get-started中几个目录导src/nifty下,目录结构如下
$ tree -I node_modules -L 3
.
├── package-lock.json
├── package.json
├── src
│ ├── app.vue
│ ├── index.html
│ ├── index.js
│ ├── nifty
│ │ ├── css
│ │ ├── img
│ │ ├── js
│ │ ├── plugins
│ │ └── premium
│ └── pages
│ ├── home.vue
│ ├── main.vue
│ └── setting.vue
└── webpack.config.js
src/pages/container.vue
另外,的图片路径需要稍作调整,如果遇到不存在的图片,需要到nifty的demo目录寻找。
使用npm run dev
打开页面调试,会报错Uncaught TypeError: Cannot read property 'setTimeout' of undefined
,将nifty.min.js中以下内容稍作修改后一切正常。
修改前
a.timeoutId&&e.clearTimeout(a.timeoutId),a.timeoutId=e.setTimeout(function(){n.trigger(t.eventName)},t.delay)}
修改后
a.timeoutId&&function(e){e.clearTimeout(a.timeoutId)},a.timeoutId=function(e){e.setTimeout(function(){n.trigger(t.eventName)},t.delay)}}
参考 https://stackoverflow.com/questions/24338761/jquery-settimeout-cannot-read-property-preventdefault-of-undefined
到这里,webpack4+vue2+nifty构建的单页应用初步完成。
6.引入Ion Icons
Ionicons is a completely open-source icon set with 700+ icons crafted for web, iOS, Android, and desktop apps.
首先安装ionicons
npm i ionicons
然后在container.vue中引入及使用css