Use webpack instead of parcel

This commit is contained in:
Pig Fang 2018-07-29 15:31:54 +08:00
parent d3abbcdf82
commit e69e7be1d9
16 changed files with 1896 additions and 2622 deletions

View File

@ -1,6 +1,6 @@
{
"presets": [
["env", {
["@babel/env", {
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
},
@ -9,13 +9,13 @@
}]
],
"plugins": [
"transform-node-env-inline"
"@babel/syntax-dynamic-import",
"@babel/proposal-optional-catch-binding"
],
"env": {
"test": {
"presets": [["env", { "targets": { "node": "current" } }]],
"plugins": [
"transform-remove-console"
"presets": [
["@babel/env", { "targets": { "node": "current" } }]
]
}
}

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
coverage
.idea/
.cache/
.cache-loader/
vendor/*
storage/textures/*
storage/update_cache/*

View File

@ -10,13 +10,12 @@
"license": "GPL-3.0",
"private": true,
"scripts": {
"dev": "parcel watch -d public resources/assets/src/components/index.js",
"build": "parcel build -d public --no-source-maps resources/assets/src/components/index.js && yarn build:polyfill",
"build:polyfill": "parcel build -d public --no-source-maps resources/assets/src/js/polyfill.js",
"dev": "webpack --mode=development --watch",
"build": "webpack --mode=production -p",
"lint": "eslint --ext=.js,.vue -f=beauty .",
"release": "gulp zip",
"test": "jest",
"codecov": "codecov -F js"
"codecov": "codecov -F js",
"postinstall": "rimraf node_modules/jest-runtime/node_modules/babel-core node_modules/jest-config/node_modules/babel-core"
},
"dependencies": {
"admin-lte": "^2.4.2",
@ -29,10 +28,8 @@
"font-awesome": "^4.7.0",
"highlight.js": "^9.12.0",
"icheck": "^1.0.2",
"jqPaginator": "^1.2.0",
"jquery": "^3.3.1",
"lodash.debounce": "^4.0.8",
"regenerator": "^0.12.3",
"skinview3d": "^1.1.0-alpha.4",
"sweetalert2": "^6.11.5",
"toastr": "^2.1.4",
@ -40,37 +37,42 @@
"vuejs-paginate": "^2.0.1"
},
"devDependencies": {
"@babel/core": "^7.0.0-beta.54",
"@babel/plugin-proposal-optional-catch-binding": "^7.0.0-beta.54",
"@babel/plugin-syntax-dynamic-import": "^7.0.0-beta.54",
"@babel/preset-env": "^7.0.0-beta.54",
"@types/jest": "^23.3.1",
"@types/jquery": "^3.3.5",
"@vue/component-compiler-utils": "^2.1.0",
"@vue/test-utils": "^1.0.0-beta.21",
"autoprefixer": "^9.0.1",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^8.2.6",
"babel-plugin-transform-node-env-inline": "^0.4.3",
"babel-plugin-transform-remove-console": "^6.9.0",
"babel-jest": "^23.4.2",
"babel-loader": "^8.0.0-beta.4",
"codecov": "^3.0.0",
"del": "^3.0.0",
"copy-webpack-plugin": "^4.5.2",
"css-loader": "^1.0.0",
"cssnano": "^4.0.4",
"eslint": "^5.2.0",
"eslint-formatter-beauty": "^3.0.0-beta.2",
"eslint-plugin-vue": "^5.0.0-beta.1",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.3",
"gulp-batch-replace": "^0.0.0",
"gulp-clean-css": "^3.9.2",
"gulp-concat": "^2.6.1",
"gulp-notify": "^3.2.0",
"gulp-sourcemaps": "^2.6.4",
"gulp-stylus": "^2.7.0",
"gulp-uglify": "^3.0.0",
"gulp-zip": "^4.1.0",
"file-loader": "^1.1.11",
"jest": "^23.4.1",
"jest-extended": "^0.7.2",
"merge2": "^1.2.1",
"parcel-bundler": "^1.9.7",
"run-sequence": "^2.2.1",
"mini-css-extract-plugin": "^0.4.1",
"postcss-loader": "^2.1.6",
"rimraf": "^2.6.2",
"style-loader": "^0.21.0",
"stylus": "^0.54.5",
"vue-hot-reload-api": "^2.3.0",
"stylus-loader": "^3.0.2",
"url-loader": "^1.0.1",
"vue-jest": "^2.6.0",
"vue-template-compiler": "^2.5.16"
"vue-loader": "^15.2.6",
"vue-template-compiler": "^2.5.16",
"webpack": "^4.16.3",
"webpack-cli": "^3.1.0",
"webpackbar": "^2.6.1",
"yaml-loader": "^0.5.0"
},
"jest": {
"transform": {

View File

@ -49,6 +49,7 @@
<script>
import * as skinview3d from 'skinview3d';
import SkinSteve from '../../images/textures/steve.png';
export default {
name: 'Previewer',
@ -94,7 +95,7 @@ export default {
domElement: this.$refs.previewer,
width: this.$refs.previewer.clientWidth,
height: this.$refs.previewer.clientHeight,
skinUrl: this.skin,
skinUrl: this.skin || SkinSteve,
capeUrl: this.cape
});
this.viewer.camera.position.z = this.initPositionZ;

View File

@ -0,0 +1,7 @@
export default [
{
path: 'user/closet',
component: () => import('./user/closet'),
el: '.content'
}
];

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,16 @@
import Vue from 'vue';
import routes from './components/route';
import './js';
Vue.config.productionTip = false;
// eslint-disable-next-line no-undef
__webpack_public_path__ = blessing.base_url + '/public/';
const route = routes.find(route => route.path === blessing.route);
if (route) {
new Vue({
el: route.el,
render: h => h(route.component)
});
}

View File

@ -0,0 +1,66 @@
import Vue from 'vue';
// $.locales = Object.create(null);
const currentLocale = null;
/**
* Load current selected language.
*
* @return void
*/
function loadLocales() {
for (const lang in $.locales) {
if ($.locales[lang]) {
$.currentLocale = $.locales[lang] || Object.create(null);
}
}
}
/**
* Translate according to given key.
*
* @param {string} key
* @param {object} parameters
* @return {string}
*/
export function trans(key, parameters = {}) {
if (!currentLocale) {
loadLocales();
}
const segments = key.split('.');
let temp = $.currentLocale || {};
for (const i in segments) {
if (!temp[segments[i]]) {
return key;
} else {
temp = temp[segments[i]];
}
}
for (const i in parameters) {
if (parameters[i] !== undefined) {
temp = temp.replace(':'+i, parameters[i]);
}
}
return temp;
}
Vue.use(_Vue => {
_Vue.prototype.$t = trans;
_Vue.directive('t', (el, { value }) => {
if (typeof value === 'string') {
el.innerHTML = trans(value);
} else if (typeof value === 'object') {
el.innerHTML = trans(value.path, value.args);
} else {
if (process.env.NODE_ENV !== 'production') {
console.warn('[i18n] Invalid arguments in `v-t` directive.');
}
}
});
});
window.trans = trans;

View File

@ -0,0 +1,3 @@
import './i18n';
import './net';
import './layout';

3
resources/assets/src/js/jquery.js vendored Normal file
View File

@ -0,0 +1,3 @@
import $ from 'jquery';
window.$ = window.jQuery = $;

View File

@ -0,0 +1,5 @@
import './jquery'; // jQuery first
import 'bootstrap';
import 'bootstrap-fileinput';
import 'admin-lte';
import 'icheck';

View File

@ -0,0 +1,10 @@
import axios from 'axios';
import { showAjaxError } from './notify';
axios.defaults.baseURL = blessing.base_url;
axios.defaults.validateStatus = status => (status >= 200 && status < 300) || status === 422;
axios.interceptors.response.use(
response => response,
showAjaxError
);

View File

@ -0,0 +1,73 @@
import $ from 'jquery';
import { trans } from './i18n';
/**
* Show message to div#msg with level
*
* @param {string} msg
* @param {string} type
* @return {void}
*/
export function showMsg(msg, type = 'info') {
$('[id=msg]')
.removeClass()
.addClass('callout')
.addClass(`callout-${type}`)
.html(msg);
}
/**
* Show modal if error occured when sending an ajax request.
*
* @param {{ response: import('axios').AxiosResponse }} response
* @return {void}
*/
export function showAjaxError({ response }) {
if (!response.data) {
return console.warn('Empty Ajax response body.');
}
const message = typeof response.data === 'object' ? response.data.message : response.data;
showModal(message.replace(/\n/g, '<br />'), trans('general.fatalError'), 'danger');
}
/**
* Show a bootstrap modal.
*
* @param {string} msg Modal content
* @param {string} title Modal title
* @param {string} type Modal type, default|info|success|warning|error
* @param {object} options All $.fn.modal options, plus { btnText, callback, destroyOnClose }
* @return {void}
*/
export function showModal(msg, title = 'Message', type = 'default', options = {}) {
const btnType = (type !== 'default') ? 'btn-outline' : 'btn-primary';
const btnText = options.btnText || 'OK';
const onClick = (options.callback === undefined) ? 'data-dismiss="modal"' : `onclick="${options.callback}"`;
const destroyOnClose = (options.destroyOnClose === false) ? false : true;
const dom = `
<div class="modal modal-${type} fade in">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">${title}</h4>
</div>
<div class="modal-body">
<p>${msg}</p>
</div>
<div class="modal-footer">
<button type="button" ${onClick} class="btn ${btnType}">${btnText}</button>
</div>
</div>
</div>
</div>`;
$(dom).on('hidden.bs.modal', function () {
destroyOnClose && $(this).remove();
}).modal(options);
}

View File

@ -1,11 +1,7 @@
<!-- Bundled styles -->
<link rel="stylesheet" href="{{ assets('css/style.css') }}">
<link rel="stylesheet" href="{{ url('public/style.css') }}">
<!-- AdminLTE color scheme -->
<link rel="stylesheet" href="{{ assets('css/skins/'.option('color_scheme').'.min.css') }}">
@if (isset($module))
<link rel="stylesheet" href="{{ assets('css/'.$module.'.css') }}">
@endif
<link rel="stylesheet" href="{{ url('public/skins/'.option('color_scheme').'.min.css') }}">
<!-- User custom styles -->
<style>{!! option('custom_css') !!}</style>

93
webpack.config.js Normal file
View File

@ -0,0 +1,93 @@
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const WebpackBar = require('webpackbar');
const devMode = !process.argv.includes('-p');
module.exports = {
entry: {
index: './resources/assets/src/index.js',
polyfill: './resources/assets/src/js/polyfill.js',
style: [
'bootstrap/dist/css/bootstrap.min.css',
'admin-lte/dist/css/AdminLTE.min.css',
'datatables.net-bs/css/dataTables.bootstrap.css',
'bootstrap-fileinput/css/fileinput.min.css',
'font-awesome/css/font-awesome.min.css',
'icheck/skins/square/blue.css',
'toastr/build/toastr.min.css',
]
},
output: {
path: __dirname + '/public',
filename: '[name].js',
chunkFilename: devMode
? '[id].js'
: '[id].[chunkhash:7].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
cacheDirectory: true
}
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.(css|styl)$/,
exclude: /node_modules/,
use: [
devMode
? 'vue-style-loader'
: MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 2 } },
'postcss-loader',
'stylus-loader'
]
},
{
test: /node_modules.*\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.ya?ml$/,
loader: 'yaml-loader'
},
{
test: /\.(png|jpg|gif|svg|woff2?|eot|ttf)$/,
loader: 'url-loader',
options: {
limit: 8192
}
}
],
noParse: /^(vue|jquery)$/
},
plugins: [
new VueLoaderPlugin(),
new WebpackBar(),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
}),
new CopyWebpackPlugin([
{
from: 'node_modules/admin-lte/dist/css/skins/skin-*.min.css',
to: 'skins',
flatten: true
},
]),
],
resolve: {
extensions: ['.js', '.vue', '.json']
},
devtool: devMode ? 'cheap-module-eval-source-map' : false,
stats: 'errors-only'
};

4166
yarn.lock

File diff suppressed because it is too large Load Diff