Webã·ã¹ãã ã®ããã³ãã¨ã³ãé«éåã§æåã«ããã¹ããã¨
ååã®ã¨ã³ããªã¼ã§ãDartã®æ¬¡ã¯ãTypeScriptãæ¤è¨¼ãããã¨æ¸ãããã©ããªããèªåã®PCã§ã¯ãVisualStudio for Webã«TypeScriptã®ãã©ã°ã¤ã³ãã¤ã³ã¹ãã¼ã«ã§ããªãã£ãã®ã§ãTypeScriptã使ããã¨ã諦ãã¾ãããã³ãã³ãã©ã¤ã³ã§ã³ã³ãã¤ã«ã¯ã§ãããã©ãããã§ã¯åä»ãè¨èªã®ã¡ãªããã§ããIDEã«ããè£å®ãåç §æ¤ç´¢ããªãã¼ã ãªãã¡ã¯ã¿ãªã³ã°ãå¹ããªãã®ã§ãã¡ãªã¿ã«ããã°ã©ãã®PCã§ã¯ãã£ããã¤ã³ã¹ãã¼ã«ã§ããã¨ã®ãã¨ããã£ããã
ã¨ããããã§ãDartãå®æ¦æå ¥ãããã¨ã決å®ãã¦Dartã§éçºããã¦ãã¾ãã
ããã³ãã¨ã³ãé«éåã®Expiresããã
ãã¦ãä»æ¥ã®æ¬é¡ãWebã·ã¹ãã ã®ããã³ãã¨ã³ãé«éåã®ã話ã§ããWebã·ã¹ãã ã®é度ã®å¤§ããªããã«ããã¯ã¨ãã¦DBè² è·ãããã¾ããããã©ã¦ã¶å´ã®ã¬ã³ããªã³ã°ãé«éåãã話ã¨ãã¦ããã³ãã¨ã³ãé«éåãããã¾ããä¸è¬ã«ã¯ã
- hmtl, css, JavaScriptãªã©ã®ããã¹ããã¼ã¿ã¯gzipå§ç¸®è»¢éãã¾ããã
- htmlããJavaScriptã®ã¤ã³ã¯ã«ã¼ãã¯ãï¼/bodyï¼ã®ç´åã«æ¸ãã¾ããã
- cssããcssãã¤ã³ãã¼ããã@importã¯ä½¿ããªãããã«ãã¾ããã
- htmlããcssã®ã¤ã³ã¯ã«ã¼ãã¯ãï¼headï¼ã¿ã°ã®ä¸ãªã©htmlã®å é è¿ãã«ç½®ãã¾ããã
- JavaScriptãcssã¯htmlã®ä¸ã«ã¤ã³ã©ã¤ã³ã§æ¥µåæ¸ããã«å¥ãã¡ã¤ã«ã«ãã¦ãã©ã¦ã¶ã®ãã£ãã·ã¥ãå¹ããã¾ããã
- éçã³ã³ãã³ãã«ã¯Expiresããããã¤ãã¦ãã©ã¦ã¶ã®ãã£ãã·ã¥ãå¹ããã¾ããã
ãªã©ãããã¾ãããããã£ã¨ãå¹æçãªã®ã¯æå¾ã®Expiresãããã®è¿½å ã§ã¯ãªãããã¨ãç¹ã«ã¹ãããªã©ã®ã¢ãã¤ã«ç«¯æ«ããã®ã¢ã¯ã»ã¹ãªã©åç·ãé
ãå ´åã«ã¯ã絶大ãªå¹æãçºæ®ããã¯ããã¨ã
ã¨ã«ãã俺ã¯é«éåã大好ããªã®ã ï¼ï¼
Expiresãããã¨ã¯
HTTPãµã¼ããã¬ã¹ãã³ã¹ãè¿ãã¨ãã«ã
Expires: Sun, 17 Feb 2014 22:28:04 JST
ã®ãããªæ¥ä»ãè¿ãã¨ããã®æå»ã¾ã§ã¯ãã®ã³ã³ãã³ãã¯å¤æ´ããªãããã¨ãã©ã¦ã¶ã«ä¼ãããã®ã§ãä¸è¨ã ã¨ã2014/2/17ãã¾ã§å¤æ´ããªãããã¨ä¼ãã¦ãã¾ããã¤ã¾ããä»ãã1å¹´å¾ãæå®ãã¦ãã¾ãã
é常ãã©ã¦ã¶ã¯ãExpiresã®æéãæ¥ãã¾ã§ã¯ã³ã³ãã³ããã¹ãã¬ã¼ã¸ã«ãã£ãã·ã¥ããäºåº¦ã¨ãµã¼ãã«åãURLããªã¯ã¨ã¹ããã¾ããï¼ãã£ãã·ã¥ããã£ã±ãã«ãªã£ãã®ã§æ¶ãã¨ãããªããã°ï¼ã
ãã©ã¦ã¶ãHTTPãªã¯ã¨ã¹ããéããªããªãã®ã§ãéä¿¡æéã¯æ¸ãããµã¼ããå¿å¯¾ããå¿
è¦ããªããAWSã®ããã«ãã©ãã£ãã¯æãããããµã¼ãè²»ç¨ãæãããã¾ãã
ã¨ãã訳ã§Expiresãããã®å¨åã¯çµ¶å¤§ã ï¼
Apacheã®å ´å
mod_expiresã追å ãã¦ã
ExpiresDefault "access plus 1 years"
ãæ¸ãã ãã§OKã§ãã
MIME-Typeå¥ã«æå®ããå ´åã¯ã
ExpiresByType text/html "access plus 1 years"
ã®ããã«ExpiresByTypeãå©ç¨ããã°OKã§ãã
ãã ãMIME-Typeã ãã§ã¯éçã³ã³ãã³ãã¨åçã³ã³ãã³ãã®åºå¥ãã¤ããªãã®ã§ãåã¯ãJavaServletå´ã§å¯¾å¿ãã¾ããï¼PHPã¨ãRubyã¨ãã§ãåæ§ã§ãããï¼ã
ã³ã³ãã³ãã®æ´æ°ã«å¯¾å¿
Expiresãããã追å ããå ´åãäºåº¦ã¨ãã©ã¦ã¶ãåãURLãã¢ã¯ã»ã¹ãã¦æ¥ãªããªãå¯è½æ§ãé«ããããéçã³ã³ãã³ããæ´æ°ããã¨ãã«åé¡ã«ãªãã¾ãããã®å ´åã¯ãURLãå¤ããããããã¾ãããé常ã¯ãã¡ã¤ã«ã®ãã¼ã¸ã§ã³çªå·ãå ¥ãããæçµæ´æ°æ¥ãå ¥ãããã§ãã
<img src="hello.png">
ã¨æ¸ã代ããã«
<img src="hello.png?20130217">
ãªã©ã®ããã«æ¸ãã¨ãããã¨ã§ããä¸è¨ã®20130217ã¯ãå½ç¶æçµæ´æ°æ¥ãã2013/02/17ãã¨ããæå³ã§ããhello.pngãæ´æ°ãã度ã«jspã®?20130217ãä¿®æ£ãã¦ããã®ã¯å¤§å¤ãããã®ã§ã
<img src=<%=Resource.get("hello.png")%> >
ã¨ããããã«Resource.get()ãéãããã«ãã¾ãããResourceã¯ã©ã¹ã¯ãèªä½ã®ã¯ã©ã¹ã§éçã³ã³ãã³ãã®URLãå
¥åããã®æçµæ´æ°æ¥ããï½URLï½?lm=YYYYMMddHHmmssãå½¢å¼ã§è¿ããã®ã§ãã
Resource#get()ã¡ã½ãããæçµæ´æ°æ¥ãå¾ãæ¹æ³ã§ããããããã°ã¢ã¼ãã¨ãªãªã¼ã¹ã¢ã¼ãã®2ã¤ãç¨æãã¾ããããããã°ã¢ã¼ãã§ã¯ããªã¯ã¨ã¹ããããURLãåå¨ãããã¼ã«ã«ã®ãã¡ã¤ã«ã®æçµæ´æ°æ¥ãã¿ã¦ãããè¿ãã¾ãã
ãªãªã¼ã¹ã¢ã¼ãã§ã¯ãäºåã«ããããã¡ã¤ã«ã§ä½æããlastModified.propertiesãã¡ã¤ã«ãåç
§ãé«éã«ã¬ã¹ãã³ã¹ãããã®ã§ããlastModified.propertiesãã¡ã¤ã«ã¯ããã¼ãURLãå¤ãYYYYMMddHHmmsså½¢å¼ã®æ´æ°æ¥ã«ãªã£ã¦ãã¾ããæ¬çªç°å¢ã«ãããã¤ããã¨ãã«ããããèµ·åãã¦lastModified.propertiesãæ´æ°ãã¾ããlastModified.propertiesãã¡ã¤ã«ã¯æ´æ°ãããã¨Tomcatãæç¥ãã¦èªåãªãã¼ããã¦ããã¾ãããã以å¤ã®ã¨ãã®propertiesãã¡ã¤ã«ã®åç
§ã§ã¯Javaã®ã©ã¤ãã©ãªå
ã§propertiesãã¡ã¤ã«ããã£ãã·ã¥ãã¦ããã¦ãã¦ã¡ã¢ãªã¢ã¯ã»ã¹ãããªãã®ã§é«éã§ãã
æ¡å¼µå
ã¡ãªã¿ã«åã管çãã¦ããããã¸ã§ã¯ãã§ã¯ãéçã³ã³ãã³ãã¯*.css, *.js, *.pngãªã©ã®ããã«é常ã®æ¡å¼µåã使ããåçã³ã³ãã³ãã¯å®æ
ãServletã§ãJSPã§ãã¬ã¹ãã³ã¹ãtext/htmlã§ãimage/pngã§ãtext/cssã§ãtext/javascriptã§ãæ¡å¼µåã*.jspã¨ãã¦ããã
CDNï¼ã³ã³ãã³ãããªããªãããã¯ã¼ã¯ï¼ãªã©ã®ãã£ãã·ã¥ãå¹ãããæã«ãåçãéçãã§åããã»ããããã®ã§ã
ãã³ããã¼ã¯
é«éåãçµã¿è¾¼ãã çµæã
å 容 | é«éåå | é«éåå¾ |
---|---|---|
3Gã§ã®ãã¼ã¸ã表示ãããã¾ã§ã®æé | 9ç§ | 1ç§ |
LANã§ã®ãã¼ã¸ã表示ãããã¾ã§ã®æé | 700ms | 200ms |
転éé | 1Mbyte | 70kbyte |
ã¨ãã訳ã§åçã«é«éåããã¾ãããã¡ãªã¿ã«è»¢éé70kbyteã¨ããã®ã¯éçã³ã³ãã³ãããã¹ã¦ãã£ãã·ã¥ã«ãããããå ´åï¼ã¤ã¾ãåãã¦ãµã¤ãã«è¨ªããã¨ãã§ã¯ãªã2度ç®ä»¥éï¼ã§ãã転éé70kbyteã¨ããã®ã¯ããã¹ã¦jspãã¬ã¹ãã³ã¹ããHTMLã§ããããgzipå§ç¸®ããã¨9kbyteã«æ¸ãã¾ãããç»åã¬ã¹ãã³ã¹ã¯ã¼ãã«ã
ã¤ã¾ãgzipå§ç¸®ããã¦70kbyteã9kbyteã«ãªã£ã¦ã1Mbyteã®ç»åãæ¸ããªããã°å¹æãªããç»åã¬ã¹ãã³ã¹ã0ã«ããä¸ã§gzipå§ç¸®ã¯å¹æãããã¨ã
ãã¨è»¢ééã®å½±é¿ã¯ãããªããã®ã®cssã®ãã£ãã·ã¥ãããããã¼ã¸ã¬ã³ããªã³ã°ã«å¤§ããå½±é¿ãã¾ãããªã«ãcssãã¡ã¤ã«ãå±ããªããã°ã»ã¼ã¬ã³ããªã³ã°ã¯é²ã¾ãªãã®ã§ã
é«éåï¼é«éåï¼é«éåï¼
Resource.get()ã®ã½ã¼ã¹
Resource.get()ã®å®ä½ã¯ãä¸è¨ã®ãããªæãã
public class Resource { /** * URLãå ¥åãã¦YYYYMMddHHmmsså½¢å¼ã®æ¥ä»ãè¿ã<br> * ä¾) å ¥å css/base.css åºå 201302101415 * * @param uri * @return ã¿ã¤ãããªãã¨ãã¯ã"" */ public static String getDate(String uri) { ResourceBundle settings = ResourceBundle.getBundle("settings"); if ("true".equalsIgnoreCase(settings.getString("debug.mode")) == false) {// ãªãªã¼ã¹ã¢ã¼ãã®ã¨ã ResourceBundle lm = ResourceBundle.getBundle("lastModified"); if (lm.containsKey(uri)) { return lm.getString(uri); } else { ErrorUtil.sendInfo(uri + " is not found in lastModified.properties."); return ""; } } else {// ãããã°ã¢ã¼ãã®ã¨ã try { SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMddHHmmss"); String path = settings.getString("servlet.context") + '/' + uri; Path p = FileSystems.getDefault().getPath(path); FileTime t = Files.getLastModifiedTime(p); Date d = new Date(t.toMillis()); return sdf.format(d); } catch (IOException e) { ErrorUtil.sendInfo(uri + " is not found at Resource#getDate() in debug mode."); return ""; } } } /** * URLãå ¥åãã¦ã "{url}?YYYYMMddHHmmss"ããè¿ãï¼ããã«ã¯ã©ã¼ãããçï¼<br> * ä¾) å ¥å css/base.css åºå "css/base.css?lm=201302101415" * * @param uri * @return */ public static String get(String uri) { String date = getDate(uri); return "\"" + (date.length() > 0 ? uri + "?lm=" + date : uri) + "\""; } }
StaticResourceServlet.java
ã.cssãã.pngãã.jsã®éçã³ã³ãã³ããã¬ã¹ãã³ã¹ããServletã®ã½ã¼ã¹ã¯ä¸è¨ã«ãªãã¾ãã
@WebServlet(urlPatterns = { "*.css", "*.js", "*.png", "*.jpg", "*.jpeg", "*.gif" }) public class StaticResourceServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { doNext(request, response); } catch (Exception e) { ErrorUtil.sendError(e); throw new ServletException(); } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { doNext(request, response); } catch (Exception e) { ErrorUtil.sendError(e); throw new ServletException(); } } /** * ã¡ã¤ã³å¦ç * * @param request * @param response * @throws Exception */ private void doNext(HttpServletRequest req, HttpServletResponse res) throws Exception { String uri = req.getRequestURI(); String contextPath = req.getServletContext().getContextPath() + '/'; String fname = uri.substring(contextPath.length()); String realPath = req.getServletContext().getRealPath("") + File.separator + fname; if (uri.indexOf("WEB-INF") != -1) {// WEB-INFãå«ã¾ãã¦ããã¨ã throw new Exception("URLã«WEB-INFãå«ã¾ãã¦ãã¾ã"); } if (uri.indexOf("..") != -1) {// ..ãå«ã¾ãã¦ããã¨ã throw new Exception("URLã«..ãå«ã¾ãã¦ãã¾ã"); } if (uri.endsWith(".js")) {// JavaScriptã®ã¨ã res.setCharacterEncoding("UTF-8"); res.setContentType("text/javascript"); } else if (uri.endsWith(".css")) {// CSSã®ã¨ã res.setCharacterEncoding("UTF-8"); res.setContentType("text/css"); } else if (uri.endsWith(".png")) {// pngã®ã¨ã res.setContentType("image/png"); } else if (uri.endsWith(".jpg") || uri.endsWith(".jpeg")) {// jpegã®ã¨ã res.setContentType("image/jpeg"); } else if (uri.endsWith(".gif")) {// gifã®ã¨ã res.setContentType("image/gif"); } else { throw new Exception("ãµãã¼ããã¦ããªãæ¡å¼µå"); } ResponseUtil.setExpiresHeader(res);// Expiresããã if (req.getParameter("lm") == null) {// lmãã©ã¡ã¼ã¿ããªãã¨ã ErrorUtil .sendInfo(uri + "ã®ãªã¯ã¨ã¹ãã§lmãã©ã¡ã¼ã¿ãã¤ãã¦ãã¾ãããExpiresãããé«éåã«å¿ è¦ã§ãã at StaticResourceServlet"); } ByteArrayOutputStream baos = null; BufferedInputStream bis = null; ByteArrayInputStream bais = null; try { baos = new ByteArrayOutputStream(); bis = new BufferedInputStream(new FileInputStream(realPath)); // ãã¡ã¤ã«ããã¡ã¢ãªã¸ã³ãã¼ byte[] buf = new byte[4096]; int size; while ((size = bis.read(buf)) >= 0) { baos.write(buf, 0, size); } // ã¡ã¢ãªããã¬ã¹ãã³ã¹ã¸åºå res.setContentLength(baos.size());// Content-Lengthããã bais = new ByteArrayInputStream(baos.toByteArray()); ServletOutputStream out = res.getOutputStream(); while ((size = bais.read(buf)) >= 0) { out.write(buf, 0, size); } out.flush(); } finally { if (bis != null) { try { bis.close(); } catch (Exception e) { } } if (baos != null) { try { baos.close(); } catch (Exception e) { } } if (bais != null) { try { bais.close(); } catch (Exception e) { } } } } }
ãã®ä»ã®ãã¿ã¼ã³
ãã¡ã¤ã«ã·ã¹ãã ä¸ã«ãã®ã¾ã¾ãã¡ã¤ã«ãç½®ããã¦ããéçã³ã³ãã³ã以å¤ã«ãDBã«éçã³ã³ãã³ããããå ´åã¯ãDBã®ãã£ã¼ã«ãã«LastUpdateãªã©ã®TIMESTAMPåãç¨æãã¦ãResource.get()ã§åããããã«ãã¦ãã¾ãã
ãã¨ãJavaScriptããéçã³ã³ãã³ãã®æçµæ´æ°æ¥ãåãé¨åã§ã¯ãJavaScriptçã®Resource.get()ç¸å½ã®ã¡ã½ããï¼å
容ã¯URLã¨æ´æ°æ¥ã®é£æ³é
åãã¼ã¿ãåãè¾¼ãã ãã®ï¼ããµã¼ããã¬ã¹ãã³ã¹ããããã«ãã¦ãã¾ãã
æåã«ããã¾ãããï¼
ãã®ä»çµã¿ã§ãããããã¸ã§ã¯ãã®éçºçµäºç´åã§ããã¯ãã«ãªãã¾ããããResource.get()ã«æ¸ãæãç®æãè¨å¤§ã ã£ããããæ»ã«ããã§ããã
æ»ã«ããã§ããã価å¤ã¯ããã®ã§çãããã£ãæ¹ãããã§ãããã§ããã°ããã¸ã§ã¯ãã®éå§æã«ä»çµã¿ãå°å
¥ãã¦ãããæ¹ãè³¢æã§ãã
é«éåï¼é«éåï¼é«éåï¼
ââ
ã¢ããªåè¨éçºãWebã·ã¹ãã åè¨éçºãè¡ã£ã¦ãã¾ãã以ä¸èªç¤¾è£½åã
URL:ibisMail Freeã®ãã¦ã³ãã¼ããã¬ãã¥ã¼ã¯こちら
URL:ibisMail for iPhoneã®ãã¦ã³ãã¼ããã¬ãã¥ã¼ã¯こちら
URL:ibisMail for iPadã®ãã¦ã³ãã¼ããã¬ãã¥ã¼ã¯こちら
URL:ibisPaintã®ãã¦ã³ãã¼ããã¬ãã¥ã¼ã¯こちら ãµã¤ãã¯ãibispaint.com
ãæè¦ãè¦æã¯Twitterãã: @kamiyan