Browse Source

Change asset loader

Sotaro KARASAWA 9 years ago
parent
commit
a2bce3e3e2

+ 13 - 15
gulpfile.js

@@ -1,5 +1,7 @@
 'use strict';
 
+var fs = require('fs');
+
 var gulp   = require('gulp');
 var sass   = require('gulp-sass');
 var cssmin = require('gulp-cssmin');
@@ -49,10 +51,10 @@ var js = {
 
   bundled:      dirs.jsDist + '/bundled.js',
   dist:         dirs.jsDist + '/crowi.js',
+  app:          dirs.jsDist + '/app.js',
   admin:        dirs.jsDist + '/admin.js',
   form:         dirs.jsDist + '/form.js',
   presentation: dirs.jsDist + '/presentation.js',
-  app:          dirs.jsDist + '/app.js',
 
   clientWatch: ['resource/js/**/*.js'],
   watch: ['test/**/*.test.js', 'app.js', 'lib/**/*.js'],
@@ -67,15 +69,16 @@ var cssIncludePaths = [
 ];
 
 gulp.task('js:del', function() {
-  var fileList = [
-    js.dist,
-    js.bundled,
-    js.admin,
-    js.form,
-    js.presentation,
-    js.app,
-  ];
-  fileList = fileList.concat(fileList.map(function(fn){ return fn.replace(/\.js/, '.min.js');}));
+  var fileList = [];
+
+  var actualFiles = fs.readdirSync(dirs.jsDist);
+  fileList = actualFiles.map(function(fn){
+    if (!fn.match(/.js(on)?$/)) {
+      return false
+    }
+    return dirs.jsDist + '/' + fn;
+  }).filter((v) => v);
+
   return del(fileList);
 });
 
@@ -94,12 +97,7 @@ gulp.task('webpack', ['js:concat'], function() {
 
 gulp.task('js:min', ['webpack'], function() {
   var fileList = [
-    js.dist,
     js.bundled,
-    js.admin,
-    js.form,
-    js.presentation,
-    js.app,
   ];
 
   fileList.forEach(function(jsfile) {

+ 21 - 0
lib/crowi/index.js

@@ -27,6 +27,13 @@ function Crowi (rootdir, env)
   this.viewsDir  = path.join(this.libDir, 'views') + sep;
   this.mailDir   = path.join(this.viewsDir, 'mail') + sep;
 
+  this.assets    = {};
+  try {
+    this.assets = require(this.publicDir + '/js/manifest.json') || {};
+  } catch (e) {
+    // ignore
+  }
+
   this.config = {};
   this.searcher = null;
   this.mailer = {};
@@ -97,6 +104,20 @@ Crowi.prototype.getConfig = function() {
   return this.config;
 };
 
+Crowi.prototype.getAssetList = function() {
+  if (this.node_env !== 'development') {
+    return this.assets;
+  }
+
+  // reload manifest
+  try {
+    this.assets = require(this.publicDir + '/js/manifest.json') || {};
+  } catch (e) {
+    // ignore
+  }
+  return this.assets;
+};
+
 // getter/setter of model instance
 //
 Crowi.prototype.model = function(name, model) {

+ 14 - 0
lib/util/swigFunctions.js

@@ -10,6 +10,20 @@ module.exports = function(crowi, app, req, locals) {
     return req.csrfToken;
   };
 
+  locals.assets = function(file) {
+    var assetList = crowi.getAssetList();
+    var baseName = file.match(/\/([^\/]+)$/)[1];
+
+    var baseNameWithHash = '';
+    if (assetList[baseName]) {
+      baseNameWithHash = assetList[baseName];
+    } else {
+      return file;
+    }
+
+    return file.replace(baseName, baseNameWithHash);
+  };
+
   locals.googleLoginEnabled = function() {
     var config = crowi.getConfig()
     return config.crowi['google:clientId'] && config.crowi['google:clientSecret'];

+ 1 - 1
lib/views/_form.html

@@ -61,4 +61,4 @@
   <div class="file-module hidden">
   </div>
 </div>
-<script src="/js/form{% if env  == 'production' %}.min{% endif %}.js"></script>
+<script src="{{ assets('/js/form.js') }}"></script>

+ 1 - 1
lib/views/layout/admin.html

@@ -1,6 +1,6 @@
 {% extends '2column.html' %}
 
 {% block footer %}
-  <script src="/js/admin{% if env  == 'production' %}.min{% endif %}.js"></script>
+  <script src="{{ assets('/js/admin.js') }}"></script>
 {% endblock footer %}
 

+ 3 - 2
lib/views/layout/layout.html

@@ -12,6 +12,7 @@
   <meta name="viewport" content="width=device-width,initial-scale=1">
 
   <link rel="stylesheet" href="/css/crowi{% if env  == 'production' %}.min{% endif %}.css">
+
   <script src="/js/bundled{% if env  == 'production' %}.min{% endif %}.js"></script>
   <link href='//fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
 </head>
@@ -130,6 +131,6 @@
 </body>
 {% endblock %}
 
-<script src="/js/crowi{% if env  == 'production' %}.min{% endif %}.js"></script>
-<script src="/js/app{% if env  == 'production' %}.min{% endif %}.js"></script>
+<script src="{{ assets('/js/crowi.js') }}"></script>
+<script src="{{ assets('/js/app.js') }}"></script>
 </html>

+ 2 - 2
lib/views/page_presentation.html

@@ -27,7 +27,7 @@
       </div>
     </div>
 
-    <script src="/js/crowi{% if env  == 'production' %}.min{% endif %}.js"></script>
-    <script src="/js/presentation{% if env  == 'production' %}.min{% endif %}.js"></script>
+    <script src="{{ assets('/js/crowi.js') }}"></script>
+    <script src="{{ assets('/js/presentation.js') }}"></script>
   </body>
 </html>

+ 1 - 0
package.json

@@ -95,6 +95,7 @@
     "time": "~0.11.0",
     "vinyl-source-stream": "~1.1.0",
     "webpack": "~1.13.0",
+    "webpack-manifest-plugin": "~1.0.1",
     "webpack-stream": "~3.1.0"
   },
   "devDependencies": {

+ 0 - 2
resource/js/app.js

@@ -33,5 +33,3 @@ Object.keys(componentMappings).forEach((key) => {
     ReactDOM.render(componentMappings[key], elem);
   }
 });
-
-

+ 10 - 5
webpack.config.js

@@ -1,17 +1,19 @@
 var path = require('path');
 var webpack = require('webpack');
 
+var ManifestPlugin = require('webpack-manifest-plugin');
+
 var config = {
   entry: {
-    app: './resource/js/app.js',
-    crowi: './resource/js/crowi.js',
+    app:          './resource/js/app.js',
+    crowi:        './resource/js/crowi.js',
     presentation: './resource/js/crowi-presentation.js',
-    form: './resource/js/crowi-form.js',
-    admin: './resource/js/crowi-admin.js',
+    form:         './resource/js/crowi-form.js',
+    admin:        './resource/js/crowi-admin.js',
   },
   output: {
     path: path.join(__dirname + "/public/js"),
-    filename: "[name].js"
+    filename: "[name].[hash].js"
   },
   resolve: {
     modulesDirectories: [
@@ -47,4 +49,7 @@ if (process.env && process.env.NODE_ENV !== 'development') {
     }),
   ];
 }
+
+config.plugins.push(new ManifestPlugin());
+
 module.exports = config;