Thi thoảng trong lúc rảnh dỗi, có khi nào bạn thử F12 lên để xem mấy website
nổi tiếng họ đang thiết kế các thẻ html
như thế nào, hay thử nghịch xem mấy file js
trên các product xem họ code như thế nào không ?
Ví dụ như khi F12 lên xem các thẻ element
của google. Có ai thắc mắc như mình là tại sao các thẻ class name nó được định nghĩa không theo một quy tắc nào không =))
Hay là khi soi các file js của các trang web bạn thường thấy các function định nghĩa rất linh tinh
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">function</span> <span class="token constant">P</span><span class="token punctuation">(</span>e<span class="token punctuation">,</span> t<span class="token punctuation">,</span> o<span class="token punctuation">,</span> i<span class="token punctuation">)</span> <span class="token punctuation">{</span> o<span class="token punctuation">.</span>updateBound <span class="token operator">=</span> i<span class="token punctuation">,</span> window<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'resize'</span><span class="token punctuation">,</span> o<span class="token punctuation">.</span>updateBound<span class="token punctuation">,</span> <span class="token punctuation">{</span> passive<span class="token punctuation">:</span> <span class="token operator">!</span><span class="token number">0</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> r <span class="token operator">=</span> <span class="token function">n</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token constant">H</span><span class="token punctuation">(</span>r<span class="token punctuation">,</span> <span class="token string">'scroll'</span><span class="token punctuation">,</span> o<span class="token punctuation">.</span>updateBound<span class="token punctuation">,</span> o<span class="token punctuation">.</span>scrollParents<span class="token punctuation">)</span><span class="token punctuation">,</span> o<span class="token punctuation">.</span>scrollElement <span class="token operator">=</span> r<span class="token punctuation">,</span> o<span class="token punctuation">.</span>eventsEnabled <span class="token operator">=</span> <span class="token operator">!</span><span class="token number">0</span><span class="token punctuation">,</span> o <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token constant">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>eventsEnabled <span class="token operator">||</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token constant">P</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>reference<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>options<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>scheduleUpdate<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Tẩt nhiên là phải có lí do cả chứ nhìn vào class name kia mà debug code thì có mà toang …
Lý do
Đối với các ứng dụng hiện đại ngoài việc ứng dụng chạy được còn phải quan tâm đến nhiều yếu tố như tốc độ, bảo mật, tránh sao chép ý tưởng …
Việc minify các file js
, css
hay obfuscate
các class name sẽ có những ưu điểm sau.
- Giảm kích thước của các file js đó đi, giúp client load những file đó nhanh hơn
- Giấu đi các
source code
, tránh ăn cắp ý tưởng - Tránh việc sử dụng các
extension
can thiệp vào UI - ….
Minify
Cách hoạt động
Minify là một kĩ thuật sử dụng tool npm
nào đó như uglify-js
, minifier
, babel-minify
để tối giản code của bạn.
Cách tối giản thì có rất nhiều phương pháp như rút ngắn tên biến, tên hàm còn a, b, C … loại bỏ các dấu xuống dòng, khoảng trắng, index …
Hoặc đơn giản là convert logic sau
1 2 3 4 5 | <span class="token comment">//Turn this</span> status<span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token comment">//Into this</span> status<span class="token punctuation">:</span> <span class="token operator">!</span><span class="token number">0</span> |
Như chúng ta có thể thấy chữ true
tốn đến 4 kí tự, trong khi !0
chỉ tốn có 2 kí tự.
Đôi khi mình cũng thắc mắc là có khi nào khi minify cách function bị trùng tên ???
Thực ra là đôi khi bạn thấy có vẻ các function có tên giống nhau thế thôi nhưng được đặt ở các scope
khác nhau nên không bị ảnh hưởng.
Bạn có thể test việc minify thông qua một số trang online, ví dụ như Uglify JS. Ta test một đoạn code đơn giản sau đây.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">function</span> <span class="token function">selectionSort</span><span class="token punctuation">(</span>array<span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> array<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token keyword">let</span> idmin <span class="token operator">=</span> i<span class="token punctuation">;</span> <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> j <span class="token operator">=</span> i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span> j <span class="token operator"><</span> array<span class="token punctuation">.</span>length<span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token keyword">if</span><span class="token punctuation">(</span>array<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator"><</span> array<span class="token punctuation">[</span>idmin<span class="token punctuation">]</span><span class="token punctuation">)</span> idmin <span class="token operator">=</span> j<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// swap</span> <span class="token keyword">let</span> t <span class="token operator">=</span> array<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span> array<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> array<span class="token punctuation">[</span>idmin<span class="token punctuation">]</span><span class="token punctuation">;</span> array<span class="token punctuation">[</span>idmin<span class="token punctuation">]</span> <span class="token operator">=</span> t<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Sau khi được minify thì đã tiết kiệm được 68% kích thước
1 2 | <span class="token keyword">function</span> <span class="token function">selectionSort</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> e<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span>e<span class="token operator"><</span>t<span class="token punctuation">.</span>length<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>e<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token keyword">let</span> l<span class="token operator">=</span>e<span class="token punctuation">;</span><span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> n<span class="token operator">=</span>e<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">;</span>n<span class="token operator"><</span>t<span class="token punctuation">.</span>length<span class="token punctuation">;</span>n<span class="token operator">++</span><span class="token punctuation">)</span>t<span class="token punctuation">[</span>n<span class="token punctuation">]</span><span class="token operator"><</span>t<span class="token punctuation">[</span>l<span class="token punctuation">]</span><span class="token operator">&&</span><span class="token punctuation">(</span>l<span class="token operator">=</span>n<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">let</span> n<span class="token operator">=</span>t<span class="token punctuation">[</span>e<span class="token punctuation">]</span><span class="token punctuation">;</span>t<span class="token punctuation">[</span>e<span class="token punctuation">]</span><span class="token operator">=</span>t<span class="token punctuation">[</span>l<span class="token punctuation">]</span><span class="token punctuation">,</span>t<span class="token punctuation">[</span>l<span class="token punctuation">]</span><span class="token operator">=</span>n<span class="token punctuation">}</span><span class="token punctuation">}</span> |
Khi nào nên minify
Thực tế thì chúng ta chỉ minify trên production, mình từng thấy vài bạn chạy npm run production
trên local
(faceplam) …
Vì đơn giản là cải thiện kích thước file ở local không giải quyết được vấn để của ứng dụng, đôi khi nó lại là con dao hai lưỡi, khi minify chúng ta sẽ khó debug code hơn.
Để chứng minh việc minify
giúp giảm kích thước file chúng ta có thể test như sau, ví dụ ở đây mình sử dụng Laravel
+ webpack
.
Khi run npm run dev
(Không minify)
1 2 3 4 5 6 7 8 9 10 11 | <span class="token constant">DONE</span> Compiled successfully <span class="token keyword">in</span> <span class="token number">947</span>ms <span class="token number">4</span><span class="token punctuation">:</span><span class="token number">33</span><span class="token punctuation">:</span><span class="token number">13</span> <span class="token constant">PM</span> Asset Size Chunks Chunk Names <span class="token operator">/</span>css<span class="token operator">/</span>app<span class="token punctuation">.</span>css <span class="token number">208</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> <span class="token operator">/</span>css<span class="token operator">/</span>lp<span class="token punctuation">.</span>css <span class="token number">237</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> <span class="token operator">/</span>css<span class="token operator">/</span>reporter<span class="token punctuation">.</span>css <span class="token number">219</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> <span class="token operator">/</span>css<span class="token operator">/</span>reporter_homepage<span class="token punctuation">.</span>css <span class="token number">1.75</span> KiB mix <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> mix <span class="token operator">/</span>js<span class="token operator">/</span>app<span class="token punctuation">.</span>js <span class="token number">775</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> <span class="token operator">/</span>js<span class="token operator">/</span>lp<span class="token punctuation">.</span>js <span class="token number">257</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> <span class="token operator">/</span>js<span class="token operator">/</span>reporter<span class="token punctuation">.</span>js <span class="token number">582</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> |
Khi run npm run production
(Apply minify)
1 2 3 4 5 6 7 8 9 10 11 | <span class="token constant">DONE</span> Compiled successfully <span class="token keyword">in</span> <span class="token number">1763</span>ms <span class="token number">4</span><span class="token punctuation">:</span><span class="token number">33</span><span class="token punctuation">:</span><span class="token number">25</span> <span class="token constant">PM</span> Asset Size Chunks Chunk Names <span class="token operator">/</span>css<span class="token operator">/</span>app<span class="token punctuation">.</span>css <span class="token number">207</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> <span class="token operator">/</span>css<span class="token operator">/</span>lp<span class="token punctuation">.</span>css <span class="token number">229</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> <span class="token operator">/</span>css<span class="token operator">/</span>reporter<span class="token punctuation">.</span>css <span class="token number">216</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> <span class="token operator">/</span>css<span class="token operator">/</span>reporter_homepage<span class="token punctuation">.</span>css <span class="token number">1.41</span> KiB <span class="token number">0</span> <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> mix <span class="token operator">/</span>js<span class="token operator">/</span>app<span class="token punctuation">.</span>js <span class="token number">761</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> <span class="token operator">/</span>js<span class="token operator">/</span>lp<span class="token punctuation">.</span>js <span class="token number">210</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> <span class="token operator">/</span>js<span class="token operator">/</span>reporter<span class="token punctuation">.</span>js <span class="token number">577</span> KiB <span class="token punctuation">[</span>emitted<span class="token punctuation">]</span> |
Các bạn có thấy sự khác biệt chưa, nhớ sử dụng minify nhé
Obfuscate CSS class names
Trước khi đi vào cách hoạt động chúng ta có công thức đơn giản sau
Obfuscated CSS class names == Giảm kích thước file == Giảm thời gian để truyền trải qua mạng.
Đã bao giờ bạn từng thiết kế một button
với class name như sau
<button class=”button button-color-red button–active”>title</button>
Việc Obfuscate
có thể giúp các class name của bạn được tối giản hơn. Giảm thiểu kí tự cũng như tránh sự can thiệp của các extension
.
Modules CSS giải quyết vấn đề đóng gói trong css, giúp định nghĩa lại các class name bao gồm các tên class-name, scopce, hàm băm ngẫu nhiên. Các class name có thể được định nghĩa bằng thuộc tính localIdentName
. Ví dụ như [name]___[local]___[hash:base64:5]
Đi vào ví dụ thực tế khi ta sử dụng CSS modules
với React
và Webpack
.
Button.css
1 2 3 4 5 6 7 8 9 10 11 | <span class="token punctuation">.</span>button <span class="token punctuation">{</span> font<span class="token operator">-</span>size<span class="token punctuation">:</span> <span class="token number">20</span>px<span class="token punctuation">;</span> color<span class="token punctuation">:</span> black<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">.</span>button<span class="token operator">--</span>color<span class="token operator">-</span>red <span class="token punctuation">{</span> color<span class="token punctuation">:</span> red<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">.</span>button<span class="token operator">--</span>active <span class="token punctuation">{</span> color<span class="token punctuation">:</span> green<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Button.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> PropTypes <span class="token keyword">from</span> <span class="token string">'prop-types'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> classNames <span class="token keyword">from</span> <span class="token string">'classnames/bind'</span><span class="token punctuation">;</span> <span class="token keyword">import</span> styles <span class="token keyword">from</span> <span class="token string">'./css/Button.scss'</span><span class="token punctuation">;</span> <span class="token keyword">const</span> cx <span class="token operator">=</span> classNames<span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>styles<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">Button</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> label<span class="token punctuation">,</span> color<span class="token punctuation">,</span> isActive <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> cssClasses <span class="token operator">=</span> <span class="token function">cx</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token string">'button'</span><span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token string">'button--color-red'</span><span class="token punctuation">:</span> <span class="token punctuation">(</span>color <span class="token operator">===</span> <span class="token string">'primary'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'button--active'</span><span class="token punctuation">:</span> isActive<span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>button className<span class="token operator">=</span><span class="token punctuation">{</span>cssClasses<span class="token punctuation">}</span><span class="token operator">></span> <span class="token punctuation">{</span>label<span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> Button<span class="token punctuation">.</span>propTypes <span class="token operator">=</span> <span class="token punctuation">{</span> label<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>string<span class="token punctuation">,</span> color<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>string<span class="token punctuation">,</span> isActive<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>bool<span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> Button<span class="token punctuation">;</span> |
webpack.config.js / loaders section
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token punctuation">{</span> test<span class="token punctuation">:</span> <span class="token regex">/.css$/</span><span class="token punctuation">,</span> use<span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> loader<span class="token punctuation">:</span> <span class="token string">'style-loader'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> loader<span class="token punctuation">:</span> <span class="token string">'css-loader'</span><span class="token punctuation">,</span> options<span class="token punctuation">:</span> <span class="token punctuation">{</span> modules<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> importLoaders<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> localIdentName<span class="token punctuation">:</span> <span class="token string">'[sha1:hash:hex:4]'</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> |
- Thuộc tính modules báo cho
webpack
biết rằng cần phảiobfuscated
các class name. Bạn cũng nên đặt thuộc tính làfalse
trong quá trình phát triển để dễ dàngdebug
. - Thuộc tính localIdentName quy định định dạng của class name sau khi được obfuscation. Như ví dụ trên chúng ta sẽ quy định class name gồm 4 kí tự, được endcode bằng sha1.
Tadaaaaaaaaaaaa, đây là thành quả.
Tổng kết
Như vậy là mình vừa giới thiệu 2 cách đơn giản để minify và obfuscate các file
css
, js
và html
. Đối với các ông lớn như Google
, Facebook
họ luôn áp dụng các phương pháp này để cải thiện sản phẩm của mình.
Hay đơn giản như Chatwork
cũng mới áp dụng kĩ thuật obfuscate
css làm cho việc cách extension
như Chat++
khó can thiệp vào UI hơn.
Cảm ơn các bạn đã theo dõi bài viết, nếu bài viết hữu ích nhớ cho mình một upvote và theo dõi để mình ra nhiều bài viết chất lượng hơn nhé.
Tham khảo: How to obfuscate CSS class names with React and Webpack